GuoXinxin

1. 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解题思路-1:

存入map中,查找差值是否也在数组中,是则返回。

注意:一个元素只能用一次,数组可以有重复元素。

 1 class Solution {
 2 public:
 3     vector<int> twoSum(vector<int>& nums, int target) {
 4         int sz = nums.size();
 5         vector<int> res;
 6         if(sz<2)
 7             return res;
 8         
 9         map<int,int> m;
10         for(int i=0;i<sz;i++){
11             m[nums[i]]=i;
12         }
13         
14         for(int i=0;i<sz-1;i++){
15             if(m.find(target-nums[i]) != m.end() && m[target-nums[i]]!=i){
16                 res.push_back(i);
17                 res.push_back(m[target-nums[i]]);
18                 break;  //不要忘记加break,否则会重复计算。
19             }      
20         }
21         return res;
22     }
23 };
24 /*
25 遇到的错误:
26     没有break:如果返回元素是索引 1与4,在1处添加1与4;在4处还会重复添加4与1。
27     if的判断条件有&&
28     后一个判断条件是索引不相等,而不是值不相等。因为数组中可能出现相同的元素。如[3,3]
29 */
View Code

解题思路-2:

使用一个HashMap(即 unordered_map)

 1 class Solution {
 2 public:
 3     vector<int> twoSum(vector<int>& nums, int target) {
 4         unordered_map<int, int> m;
 5         vector<int> res;
 6         for (int i = 0; i < nums.size(); ++i) {
 7             m[nums[i]] = i;
 8         }
 9         for (int i = 0; i < nums.size(); ++i) {
10             int t = target - nums[i];
11             if (m.count(t) && m[t] != i) {
12                 res.push_back(i);
13                 res.push_back(m[t]);
14                 break;
15             }
16         }
17         return res;
18     }
19 }; 
View Code

简洁版(推荐,一次for循环即可)

 1 class Solution {
 2 public:
 3     vector<int> twoSum(vector<int>& nums, int target) {
 4         unordered_map<int, int> m;
 5         for (int i = 0; i < nums.size(); ++i) {
 6             if (m.count(target - nums[i])) {   //当前i还没有被存入,找到的是之前存入的,因此不会出现找到的两个数是同一个元素的情况
 7                 return {i, m[target - nums[i]]};
 8             }
 9             m[nums[i]] = i;
10         }
11         return {};
12     }
13 };
View Code

 

2. 两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

解题思路:

从两个链表的头部开始计算,如果两个链表的值以及进位相加>=10,则继续进位(设置标志flag表示是否需要进位)

注意:

1)当两个链表共有长度处理完,还要处理较长的链表的剩余部分,并不是简单链接,还要考虑是否有共同相加时的进位。

2)当长的链表处理完,要考虑最高位(即最后一位是否有进位),如果有进位,添加一个新节点。

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
12         if(l1==nullptr && l2==nullptr )
13             return nullptr;
14         ListNode* res=new ListNode(0);
15         ListNode* p1=l1; 
16         ListNode* p2=l2;
17         ListNode* phead = res;
18         int flag = 0,temp=0;
19         while(p1!=nullptr && p2!=nullptr){  //处理两个链表的公共部分
20             temp = p1->val + p2->val + flag;
21             if(temp>=10){
22                 flag =1;
23                 temp = temp%10;
24             }else{
25                 flag = 0;
26             }
27             ListNode* tp = new ListNode(temp);
28             phead->next = tp;
29             phead = tp;  
30             p1=p1->next;
31             p2=p2->next;
32         }
33         ListNode* pp=nullptr;
34         if(p1 != nullptr)
35             pp=p1;
36         if(p2 != nullptr)
37             pp=p2;
38         //处理长的某个非空链表的剩余部分(注意进位问题)
39         while(pp!=nullptr){
40             temp = pp->val + flag;
41             if(temp>=10){
42                 flag =1;
43                 temp = temp%10;
44             }else{
45                 flag = 0;
46             }
47             ListNode* tp = new ListNode(temp);
48             phead->next = tp;
49             phead = tp;  
50             pp=pp->next;
51         }
52         //最高位是否需要进位
53         if(flag){
54             ListNode* tp = new ListNode(flag);
55             phead->next = tp;
56         }
57         //注意链表的返回
58         return res->next;
59     }
60 };
View Code

注意:

定义新的链表的时候:是ListNode* res=new ListNode(0); 而不是ListNode* res=nullptr; (后一种情况,空指针,没有办法访问,res->val或者res->next)

前一种定义是正确的,返回是应该返回 res->next而不是res;

简洁版:

 1 public ListNode addTwoNumbers2(ListNode l1, ListNode l2) {
 2         ListNode dummyHead = new ListNode(0);
 3         ListNode p = l1, q = l2, curr = dummyHead;
 4         int carry = 0;
 5         while (p != null || q != null) {
 6             int x = (p != null) ? p.val : 0;
 7             int y = (q != null) ? q.val : 0;
 8             int sum = carry + x + y;
 9             carry = sum / 10;
10             curr.next = new ListNode(sum % 10);
11             curr = curr.next;
12             if (p != null) p = p.next;
13             if (q != null) q = q.next;
14         }
15         if (carry > 0) {
16             curr.next = new ListNode(carry);
17         }
18         return dummyHead.next;
19     }
View Code

 

3. 无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
        请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

解题思路-1:

使用队列、集合。集合用于判断是否出现重复元素。队列用于保存出现重复元素时,当前不重复的子串(将队首重复的元素,及之前的元素删掉)。

 1 class Solution {
 2 public:
 3     int lengthOfLongestSubstring(string s) {
 4         int sz = s.size();
 5         if(sz<2)
 6             return sz;
 7         
 8         set<char> setS;
 9         queue<char> qS;
10         setS.insert(s[0]);
11         qS.push(s[0]);
12         int count = 1,temp=1;
13         for(int i=1;i<sz;i++){ //从索引1开始
14             auto iter = setS.find(s[i]);
15             if(iter!=setS.end()){ //找到元素,即出现相同元素
16                 auto itQ = qS.front();
17                 while(itQ != s[i]){
18                     qS.pop();
19                     setS.erase(itQ);
20                     temp--;
21                     itQ = qS.front();//不要忘记更新变量,指向下一个元素
22                 }     
23                 qS.pop(); // a b c a 集合与队列中已经有3个元素,对于集合,新来了a,其元素由啊a b c变为b c a。可以保持不变
24                 qS.push(s[i]); //但对于队列,其设计顺序问题,若a b c保持不变(实际上是b c a),下一次进入时,a b c 会将a弹掉(错误)
25             }else{ //没有重复元素
26                 qS.push(s[i]);
27                 setS.insert(s[i]);
28                 temp++;
29             }
30             count = max(count,temp);            
31         }
32         return count;
33     }
34 };
35 
36 //队列没有迭代器,qS.begin()是错误的
View Code

注意:1)队列(queue)没有迭代器   2)当队列中元素是 a b c时,进入元素a,应该将对首a删除,然后队尾添加a,保持相邻元素的顺序。

解题思路-2:

上述思路使用队列消耗了多余的空间。实际上使用两个指针来表示当前无重复字符的子串即可以

 1 class Solution {
 2 public:
 3     int lengthOfLongestSubstring(string s) {
 4         int sz = s.size();
 5         if(sz<2)
 6             return sz;
 7         
 8         int start=0,end=1;
 9         int count = end - start;
10         unordered_set<char> setS;
11         setS.insert(s[0]);
12         
13         for(int i=1;i<sz;i++){
14             if(setS.find(s[i])!=setS.end()){//找到重复元素
15                 while(s[start]!=s[i]){
16                     setS.erase(s[start]); //不要忘记删除队首多余的元素
17                     start++;     
18                 }
19                 start++; //两者同时后移,因为while只处理了重复元素的前面的元素,而没有考虑之后的元素
20                 end++;
21             }else{
22                 end++;
23                 setS.insert(s[i]);
24             }
25             count = max(count,end-start);
26             
27         }
28         return count;
29     }
30 };
View Code

 

4. 寻找两个有序数组的中位数

分类:

技术点:

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-04
  • 2021-12-06
  • 2021-07-28
  • 2022-01-28
  • 2022-12-23
猜你喜欢
  • 2021-12-09
  • 2021-04-09
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-26
相关资源
相似解决方案