❤ 作者主页:欢迎来到我的技术博客😎
❀ 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~*
🍊 如果文章对您有帮助,记得关注、点赞、收藏、评论⭐️⭐️⭐️
📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉
文章目录
- 一、两数之和
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 二、两数相加
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 三、无重复字符的最长子串
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 四、寻找两个正序数组的中位数
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 五、最长回文子串
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 六、正则表达式匹配
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 七、盛最多水的容器
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 八、三数之和
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 九、电话号码的字母组合
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
- 十、删除链表的倒数第 N 个结点
- 1. 题目描述
- 2. 思路分析
- 3. 代码实现
一、两数之和
1. 题目描述
2. 思路分析
最容易想到的方法是枚举数组中的每一个数 x x x,寻找数组中是否存在 t a r g e t − x target - x target−x。
使用哈希表,可以将寻找 t a r g e t − x target - x target−x 的时间复杂度降低到从 O ( N ) O(N) O(N) 降低到 O ( 1 ) O(1) O(1)。
循环一遍nums
数组,在每步循环中做两件事:
1、判断 target - nums[i]
是否出现在哈希表中;
2、将 nums[i]
插入到哈希表中。
3. 代码实现
class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int, int> heap;for (int i = 0; i < nums.size(); i ++) {int r = target - nums[i];if (heap.count(r)) return {heap[r], i};heap[nums[i]] = i;}return {};}
};
二、两数相加
1. 题目描述
2. 思路分析
(模拟人工加法) O(n)
这是一道模拟题,直接模拟列竖式做加法的过程:
- 从最低位至最高位,逐位相加,如果大于和等于10,则保留个位数字,同时向前一位加1;
- 如果最高位有进位,则需在最前面补1。
列表的题目,有个常见的技巧:
添加一个虚拟头结点:ListNode *head = new ListNode(-1);
,这样可以简化边界情况的判断。
时间复杂度:由于总共共扫描一遍,所以时间复杂度是O(n)。
3. 代码实现
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {auto dummy = new ListNode(-1), cur = dummy;int t = 0;while (l1 || l2 || t) {if (l1) t += l1->val, l1 = l1->next;if (l2) t += l2->val, l2 = l2->next;cur = cur->next = new ListNode(t % 10);t /= 10;}return dummy->next;}
};
三、无重复字符的最长子串
1. 题目描述
2. 思路分析
定义两个指针 i , j ( i < = j ) i,j(i <= j) i,j(i<=j), 表示当前扫描到的子串是 [ i , j ] [i,j] [i,j](闭区间)。扫描过程中维护一个哈希表unorderes_map<char, int> hash
, 表示 [ i , j ] [i,j] [i,j] 中每个字符出现的个数。
线性扫描,每次循环的流程如下:
- 指针 j j j 向后移一位,同时将哈希表中 s [ j ] s[j] s[j] 的计数加一:
hash[s[j]] ++;
- 假设 j j j 移动前的区间 [ i , j ] [i,j] [i,j] 中没有重复字符,则 j j j 移动后,只有 s [ j ] s[j] s[j] 可能出现2次。因此我们不断向后移动 i i i,直至区间 [ i , j ] [i,j] [i,j] 中 s [ j ] s[j] s[j] 的个数等于1为止。
3. 代码实现
class Solution {
public:int lengthOfLongestSubstring(string s) {unordered_map<char, int> heap;int res = 0;for (int i = 0, j = 0; i < s.size(); i ++) { heap[s[i]] ++;while (heap[s[i]] > 1) heap[s[j ++]] --;res = max(res, i - j + 1);}return res;}
};
四、寻找两个正序数组的中位数
1. 题目描述
2. 思路分析
3. 代码实现
五、最长回文子串
1. 题目描述
2. 思路分析
暴力枚举 O( 2 2 2^2 22)
首先枚举回文串的中心 i i i,然后分两种情况向两边扩展,直到遇到不同字符为止:
- 回文串长度是奇数,则依次判断 s [ i − k ] = = s [ i + k ] , k = 1 , 2 , 3..... s[i - k] == s[i + k], k = 1, 2,3..... s[i−k]==s[i+k],k=1,2,3.....
- 回文串长度是偶数,则依次判断 s [ i + k ] = = s [ i + k − 1 ] , k = 1 , 2 , 3.... s[i + k] == s[i + k - 1], k = 1, 2, 3.... s[i+k]==s[i+k−1],k=1,2,3....
如果遇到不同字符,则我们找到了以 i i i 为中心的回文字符串边界。
3. 代码实现
class Solution {
public:string longestPalindrome(string s) {string res;for (int i = 0; i < s.size(); i ++ ) {int l = i - 1, r = i + 1;while (l >= 0 && r < s.size() && s[l] == s[r]) l --, r ++;if (res.size() < r - l - 1) res = s.substr(l + 1, r - l - 1);l = i, r = i + 1;while (l >= 0 && r < s.size() && s[l] == s[r]) l --, r ++;if (res.size() < r - l - 1) res = s.substr(l + 1, r - l - 1);}return res;}
};
六、正则表达式匹配
1. 题目描述
2. 思路分析
3. 代码实现
七、盛最多水的容器
1. 题目描述
2. 思路分析
- 初始化: 双指针 i i i, j j j分别指向水槽的左右两端;
- 循环收窄: 直至双指针相遇时跳出;
- 更新面积最大值 r e s res res;
- 选定两板高度中的短板,向中间收窄一格;
- 返回值: 返回面积最大值 r e s res res 即可。
3. 代码实现
class Solution {
public:int maxArea(vector<int>& height) {int res = 0;for (int i = 0, j = height.size() - 1; i < j;) {res = max(res, min(height[i], height[j]) * (j - i));if (height[i] > height[j]) j --;else i ++; } return res;}
};
八、三数之和
1. 题目描述
2. 思路分析
双指针算法 O ( n 2 ) O(n^2) O(n2)
- 枚举每个数,先确定 n u m s [ i ] nums[i] nums[i],在排序后的情况下,通过双指针 j j j, k k k 分别从左边 j = i + 1 j = i + 1 j=i+1 和右边 k = n − 1 k = n - 1 k=n−1 往中间靠拢,找到 n u m s [ i ] + n u m s [ j ] + n u m s [ k ] = = 0 nums[i] + nums[j] + nums[k] == 0 nums[i]+nums[j]+nums[k]==0 的所有符合条件的搭配;
- 判重处理: 当
i > 0(i不是第一个数) && nums[i] == nums[i - 1]
,表示当前确定好的数与上一个一样,需要直接 o n t i n u e ontinue ontinue,同理,j && nums[j] == nums[j-1]
需要直接 c o n t i n u e continue continue; while(j < k - 1 && nums[i] + nums[j] + nums[k - 1] >= 0) k --
//要找到满足最小的 k k k
为什么 j < k − 1 j < k - 1 j<k−1
试探法,如果 k k k 的下一个数( k k k的左边的数)满足就用下一个数。
3. 代码实现
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> res;sort(nums.begin(), nums.end());for (int i = 0; i < nums.size(); i ++ ) {if (i && nums[i] == nums[i - 1]) continue;for (int j = i + 1, k = nums.size() - 1; j < k; j ++ ) {if (j > i + 1 && nums[j] == nums[j - 1]) continue;while (j < k - 1 && nums[i] + nums[j] + nums[k - 1] >= 0) k --;if (nums[i] + nums[j] + nums[k] == 0) {res.push_back({nums[i], nums[j], nums[k]});}}}return res;}
};
九、电话号码的字母组合
1. 题目描述
2. 思路分析
- 这是个排列组合问题,这个排列组合可以用树的形式表示出来;
- 当给定了输入字符串,比如:“23”,那么整棵树就构建完成了,如下:
- 问题转化成了从根节点到空节点一共有多少条路径。
3. 代码实现
class Solution {
public:vector<string> ans;string strs[10] = {"", "", "abc", "def","ghi", "jkl", "mno","pqrs", "tuv", "wxyz",};vector<string> letterCombinations(string digits) {if (digits.empty()) return ans;dfs(digits, 0, "");return ans;}void dfs(string& digits, int u, string path) {if (u == digits.size()) ans.push_back(path);else {for (auto c : strs[digits[u] - '0']) dfs(digits, u + 1, path + c);}}
};
十、删除链表的倒数第 N 个结点
1. 题目描述
2. 思路分析
(两次遍历) O ( L ) O(L) O(L)
- 第一次遍历求出链表的长度。
- 第二次遍历删掉指定结点。
3. 代码实现
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {auto dummy = new ListNode(-1);dummy->next = head;int len = 0;for (auto p = dummy; p; p = p->next) len ++;auto p = dummy;for (int i = 0; i < len - n - 1; i ++) p = p->next;p->next = p->next->next;return dummy->next;}
};
非常感谢您阅读到这里,如果这篇文章对您有帮助,希望能留下您的点赞👍 关注💖 分享👥 留言💬thanks!!!