当前位置: 首页 > news >正文

hot100面试150——十二周

目录

最长回文子串

最长公共子序列

多数元素

寻找重复数

合并两个有序数组

移除元素

删除有序数组的重复项

多数元素

轮转数组

买卖股票的最佳时机

买卖股票的最近时机二

跳跃游戏

跳跃游戏二

H指数

O(1) 时间插入,删除和获取随机元素


最长回文子串

解法1:动态规划

dp表整理出从【i,j】位置的子串是否是回文后寻找最长回文子串

class Solution
{
public:string longestPalindrome(string s){int n = s.size();vector<vector<bool>> dp(n, vector<bool>(n, false));dp[0][0] = true;// i <= j// 为什么可以做到不越界? 因为dp填表只会填一半for (int i = n - 1; i >= 0; i--){for (int j = i; j < n; j++){if (s[i] == s[j]){if (i == j || i + 1 == j)dp[i][j] = true;else{dp[i][j] = dp[i + 1][j - 1];}}}}string ret;for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){if (dp[i][j] && j - i + 1 > ret.size()){ret = s.substr(i, j - i + 1);}}}return ret;}
};

解法2:奇偶中心扩展算法

class Solution
{
public:string longestPalindrome(string s){int n = s.size(), cnt = 0, begin = 0;for (int i = 0; i < n; i++){// 奇数扩展int b = i - 1, e = i + 1;while (b >= 0 && e < n && s[b] == s[e]){b--;e++;}if (cnt < e - b - 1){cnt = e - b - 1;begin = b + 1;}// 偶数扩展b = i, e = i + 1;while (b >= 0 && e < n && s[b] == s[e]){b--;e++;}if (cnt < e - b - 1){cnt = e - b - 1;begin = b + 1;}}return s.substr(begin, cnt);}
};

最长公共子序列

解法:动态规划

两个字符串的dp问题

class Solution
{
public:int longestCommonSubsequence(string text1, string text2){int n = text1.size(), m = text2.size();vector<vector<int>> dp(n + 1, vector<int>(m + 1));for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){if (text1[i - 1] == text2[j - 1])dp[i][j] = dp[i - 1][j - 1] + 1;elsedp[i][j] = max(dp[i - 1][j - 1], max(dp[i - 1][j], dp[i][j - 1]));}}return dp[n][m];}
};

多数元素

解法:规律

自我举荐的方式寻找出现最多的元素

class Solution
{
public:int majorityElement(vector<int> &nums){int tmp = nums[0], cnt = 1;for (int i = 1; i < nums.size(); i++){if (tmp == nums[i])cnt++;else{if (--cnt == 0){tmp = nums[i];cnt = 1;}}}return tmp;}
};

寻找重复数

解法:快慢指针

转换为 环形链表 的找环问题

从入度为0的起点(这才保证一定能找到),也就是下标为0的节点开始,往后走,这里 next 翻译为 nums[0]

走到相遇位置时,让慢节点回到起点0处,后面快慢指针就一起走一步知道相遇,相遇点就是 环形链表的环,这里是重复数

class Solution
{
public:int findDuplicate(vector<int> &nums){int slow = 0, fast = 0;while (true){slow = nums[slow];fast = nums[nums[fast]];if (slow == fast){slow = 0;break;}}while (slow != fast){slow = nums[slow];fast = nums[fast];}return slow;}
};

合并两个有序数组

解法:逆向思路

正向比较会覆盖原有值,那就反着来

class Solution
{
public:void merge(vector<int> &nums1, int m, vector<int> &nums2, int n){int e1 = m - 1, e2 = n - 1;// e2<0 循环就没必要,结果已经在nums1中了for (int i = n + m - 1; i >= 0 && e2 >= 0; i--){// e1>=0 避免 m=0if (e1 >= 0 && nums1[e1] > nums2[e2])nums1[i] = nums1[e1--];elsenums1[i] = nums2[e2--];}}
};

移除元素

解法:模拟

把 nums 看成栈,定义 i = 0:不等于 val 值入栈,也就是将值放入 nums[i] 中,i++ 

class Solution
{
public:int removeElement(vector<int> &nums, int val){int i = 0, cnt = 0;;for (int j = 0; j < nums.size(); j++){if (nums[j] != val){nums[i++] = nums[j];cnt++;}}return cnt;// vector<int> ret;// int cnt=0;// for(auto& num:nums)// {//     if(num!=val)//     {//         ret.push_back(num);//         cnt++;//     }// }// nums=ret;// return cnt;}
};

删除有序数组的重复项

解法:模拟

定义两个指针

  • b:表示当前要覆盖的位置
  • e:表示当前值与前面值的情况,如果不相同则需要更新

让 e 进行移动,遇到当前值与前面值不同,进行更新,同时 b和e往后走一步

class Solution
{
public:int removeDuplicates(vector<int> &nums){int n = nums.size(), b = 1;// while(e<n)for (int e = 1; e < n; e++){// //里面也要限制 nums=[1,1]// while(e+1<n && nums[e]==nums[e+1]) e++;// if(e+1<n) nums[++b]=nums[++e];if (nums[e] != nums[e - 1]){nums[b++] = nums[e];}}return b;}
};

删除有序数组中的重复项0二

解法:模拟

与上题类似,只是要判断什么时候可以覆盖的:

但当前b位置的前一个数 nums[b-1] 等于 当前 nums[e] 时,说明 nums[e] 是相同元素的第三个数,不能覆盖;反之则可以在b的前面位置覆盖上 nums[e[

class Solution {
public:int removeDuplicates(vector<int>& nums) {int b = 1;if(nums.size() == 1) return b;for(int e = 2;e < nums.size();e++){if(nums[e] != nums[b-1]){nums[++b] = nums[e];}}return b + 1;}
};

多数元素

解法:自我举荐或者说,通过超过 n/2 的人投票选举出决策者

class Solution
{
public:int majorityElement(vector<int> &nums){int n = nums.size();int tmp = nums[0], cnt = 1;for (int i = 1; i < n; i++){if (tmp != nums[i]){cnt--;if (cnt == 0){tmp = nums[i];cnt = 1;}}elsecnt++;}return tmp;}
};

轮转数组

class Solution
{
public:void Reverse(int b, int e, vector<int> &nums){while (b < e){int tmp = nums[b];nums[b] = nums[e];nums[e] = tmp;b++;e--;}}void rotate(vector<int> &nums, int k){int n = nums.size();int mid = n - k % n; // 细节:可能k比n大Reverse(0, mid - 1, nums);Reverse(mid, n - 1, nums);Reverse(0, n - 1, nums);}
};

买卖股票的最佳时机

解法:模拟

定义一个变量 min_tmp 表示当前股票为最少值时我“买”入了

遍历每一天的股票,遍历到某天时如果购票“卖”出了,收益是多少,枚举更新出最大收益;同时还要更新出当前股票的“买”入的最小值

class Solution
{
public:int maxProfit(vector<int> &prices){int n = prices.size();int min_tmp = prices[0], ret = 0;for (int i = 1; i < n; i++){ret = max(ret, prices[i] - min_tmp);if (min_tmp > prices[i]){min_tmp = prices[i];}}return ret;}
};

买卖股票的最近时机二

解法:动态规划

根据状态机,也就是画图来分析有哪些状态,进而推出使用多状态dp进行解决

class Solution
{
public:int maxProfit(vector<int> &prices){int n = prices.size();vector<int> dp_buy(n), dp_sale(n);dp_buy[0] = -prices[0];for (int i = 1; i < n; i++){dp_buy[i] = max(dp_buy[i - 1], dp_sale[i - 1] - prices[i]);dp_sale[i] = max(dp_sale[i - 1], dp_buy[i - 1] + prices[i]);}return max(dp_buy[n - 1], dp_sale[n - 1]);}
};

跳跃游戏

解法:区间问题

定义指针

left:从某个位置起跳,最近到达的位置

right:从某个位置起跳,最近到达的位置

遍历确定left,就是 right 往后一位,而确定right,则要从【left,right】当中枚举中最远的位置进行更新;如果 left > right(=合法),区间不合法,就说明无法跳到最后一个下标

class Solution:def canJump(self, nums: List[int]) -> bool:n = len(nums)l, r = 0, 0while r < (n - 1):max_move = 0for i in range(l, r + 1):max_move = max(max_move, i + nums[i])l = r + 1r = max_move# [1,2] 这里不能加上 = 进行判断if l > r:return Falsereturn True

跳跃游戏二

使用上题类似的思路,在循环中使用变量进行计数

class Solution:def jump(self, nums: List[int]) -> int:n = len(nums)l, r, cnt = 0, 0, 0while r < (n - 1):cnt += 1max_move = 0for i in range(l, r + 1):max_move = max(max_move, i + nums[i])l = r + 1r = max_movereturn cnt

H指数

解法1:排序

先排序,在从左往右遍历找最大H指数

如果引用数比论文数量(大于等于引用数)小,则此时最大H指数就是引用数,反之则是论文数量(例子:【100,200】)

class Solution:def hIndex(self, citations: List[int]) -> int:h, n = 0, len(citations)citations.sort()for i in range(0, n):# 论文数量与引用次数,谁小取谁(排序后每次都是从最小引用次数的论文开始遍历)h = max(h, min(citations[i], n - i))# if citations[i]<=n-i:#     h=max(h,citations[i])# elif citations[i] >= n-i:#     h=max(h,n-i)return h

解法2:计数排序

先创建n+1的空间进行计数排序

为什么不是最大值+1的空间?        因为引用数大于n的效果与等于n是类似的,把它当做n

题目要找:并至少 有 h 篇论文被引用次数大于等于 h 的条件下最大的h

我们就倒序遍历,定义变量 s 记录当前大于等于引用数i 的论文数量,当 s >= i 时,说明我们找到了最大h:因为再往后i越小,s越大,一定满足但不是最大的h

class Solution:def hIndex(self, citations: List[int]) -> int:h, n = 0, len(citations)# 超过n的引用数量考虑的是论文数量,所以不需要统计# 计数排序cnt = [0] * (n + 1)for citation in citations:cnt[min(citation, n)] += 1s = 0for i in range(n, -1, -1):s += cnt[i]# 倒序遍历,论文的数大于等于引用数就找到了最大H指数if s >= i:return ireturn -1

O(1) 时间插入,删除和获取随机元素

解法1:使用哈希表

class RandomizedSet
{
public:RandomizedSet(){}bool insert(int val){if (_h.contains(val))return false;_h.insert(val);return true;}bool remove(int val){if (!_h.contains(val))return false;_h.erase(val);return true;}int getRandom(){std::size_t randomIndex = std::rand() % _h.size();auto it = _h.begin();std::advance(it, randomIndex);return *it;}private:unordered_set<int> _h;
};

解法2:数组 + 哈希表

创建数组和哈希表,键为 val,值为 index;定义 index = -1 表示当前最后一个知道 下标

主要在删除操作:

  • 如果在哈希表存在删除 val,哈希表删除之前要先保存 val 的下标 pos,再 erase
  • 更新数组和哈希表中的下标,数组主要是把 pos 位置的值被最后一个数给覆盖;哈希表主要是更新最后一个值的下标;因为要判断只有一个数时不需要更新哈希表,所以写代码时要先判断更新哈希表,在更新数组,-- index
class RandomizedSet
{
public:RandomizedSet() {}bool insert(int val){if (_hash.contains(val))return false;_hash[val] = ++_index;_arr[_index] = val;return true;}bool remove(int val){if (!_hash.contains(val))return false;int pos = _hash[val];_hash.erase(val);// 最后一个值放在覆盖在删除值的位置时,还是更新 _hash 中最后一个数的下标(前提是数组个数大于1)if (_index != pos)_hash[_arr[_index]] = pos;_arr[pos] = _arr[_index--];// if(_index>=0) _hash[_arr[_index]]=_index;return true;}int getRandom(){return _arr[rand() % (_index + 1)];}private:int _arr[200001];unordered_map<int, int> _hash;int _index = -1;
};

以上便是全部内容,有问题欢迎在评论区指正,感谢观看!

http://www.dtcms.com/a/537740.html

相关文章:

  • 免费网站模板psd崇明装修公司哪家好
  • 公司做网站的申请上海热点新闻
  • 《Redis 开发与运维》学习笔记[特殊字符]
  • 上海网站建设公司电网页拖拽设计工具
  • cdn网站加速有用吗网页游戏传奇霸主攻略
  • 保护你的创意!让图片拥有盲水印[特殊字符][特殊字符]
  • NEFTUNE
  • 西安优化网站技术徐州市网站开发
  • 泉州网站建设电话网站地图怎么做、
  • 二十二、DevOps:基于Tekton的云原生平台落地(三)
  • 搜狗网站收录入口万网公司注册网站
  • CUDA中__restrict__关键字的使用
  • 做热图的网站1分钟视频制作报价明细
  • 企业为什么做网站优化推广张掖市作风建设年活动网站
  • 未来做那个网站能致富爱站工具包
  • 建设一个网站系统要多久个人建站系统
  • 汽车紧固技术加速进化,推动汽车产业迈向高质量制造新阶段
  • AI结对编程:人机共创新纪元
  • 网站建设自动适应功能wordpress 开源吗
  • 专业的网站设计师房管局 网站做房查
  • 受欢迎的集团网站建设xxx网站建设与优化推广
  • 东莞市手机网站建设品牌建设项目自主验收公示的网站
  • Matplotlib指南:从入门到出版级数据可视化
  • 央企门户网站哪家做的最好seo技术顾问
  • 合肥专业做网站做网站的公司经营范围怎么写
  • 有个网站做彩盒的香奈儿网站建设策划书
  • 后台系统点击登录按钮直接跳转到目标路由下,而不是首页
  • Web Services 平台元素
  • 建站系统推荐做的高大上的网站
  • 做网站用不用thinkphpwordpress修改邮件模板