2. 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4] 输出:[7,0,8] 解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0] 输出:[0]
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] 输出:[8,9,9,9,0,0,0,1]
提示:
- 每个链表中的节点数在范围
[1, 100]内 0 <= Node.val <= 9- 题目数据保证列表表示的数字不含前导零
![]()
-
两数相加最方便的方式便是,对位数较少的数在末位补0使两数位数相同,之后同步遍历计算相加取余和进位。
View Code1 /** 2 3 * Definition for singly-linked list. 4 5 * struct ListNode { 6 7 * int val; 8 9 * ListNode *next; 10 11 * ListNode() : val(0), next(nullptr) {} 12 13 * ListNode(int x) : val(x), next(nullptr) {} 14 15 * ListNode(int x, ListNode *next) : val(x), next(next) {} 16 17 * }; 18 19 */ 20 21 class Solution { 22 23 public: 24 25 ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { 26 27 //分段法 28 29 /* 30 31 if(l1==nullptr)return l2; 32 33 if(l2==nullptr)return l1; 34 35 int nval=0; 36 37 ListNode *p; 38 39 p=l1; 40 41 while(p!=nullptr&&l2!=nullptr) 42 43 { 44 45 int v=p->val+l2->val+nval; 46 47 nval=v/10; 48 49 p->val=v%10; 50 51 if(p->next!=nullptr&&l2->next!=nullptr) 52 53 { p=p->next; 54 55 l2=l2->next; 56 57 58 }else break; 59 60 } 61 62 if(l2->next!=nullptr) 63 64 { 65 66 p->next=l2->next; 67 68 } 69 70 while(p->next!=nullptr){ 71 72 p=p->next; 73 74 int v=p->val+nval; 75 76 nval=v/10; 77 78 p->val=v%10; 79 80 } 81 82 if(nval==1) p->next=new ListNode(1); 83 84 return l1; 85 86 } 87 88 */ 89 90 //补0 91 92 int len1=0,len2=0; 93 94 ListNode*p1=l1,*p2=l2; 95 96 while(p1->next!=nullptr) 97 98 { 99 100 len1++; 101 102 p1=p1->next; 103 104 } 105 106 while(p2->next!=nullptr) 107 108 { 109 110 len2++; 111 112 p2=p2->next; 113 114 } 115 116 //p1=l1;p2=l2; 117 118 if(len1<len2){ 119 120 for(int i=0;i<len2-len1;i++) 121 122 { 123 124 p1->next=new ListNode(0); 125 126 p1=p1->next; 127 128 } 129 130 } 131 132 if(len1>len2){ 133 134 for(int i=0;i<len1-len2;i++) 135 136 { 137 138 p2->next=new ListNode(0); 139 140 p2=p2->next; 141 142 } 143 144 } 145 146 int len=(len1>=len2)?len1:len2; 147 148 p1=l1;p2=l2; 149 150 int nval=0; 151 152 while(p2!=nullptr) 153 154 { 155 156 int v=p1->val+p2->val+nval; 157 158 nval=v/10; 159 160 p1->val=v%10; 161 162 if(p1->next!=nullptr) 163 164 { 165 166 p1=p1->next; 167 168 p2=p2->next; 169 170 }else break; 171 172 } 173 174 if(nval==1) p1->next=new ListNode(1); 175 176 return l1; 177 178 } 179 180 181 };
4. 寻找两个正序数组的中位数
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。
进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?
示例 1:
输入:nums1 = [1,3], nums2 = [2] 输出:2.00000 解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4] 输出:2.50000 解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
示例 3:
输入:nums1 = [0,0], nums2 = [0,0] 输出:0.00000
示例 4:
输入:nums1 = [], nums2 = [1] 输出:1.00000
示例 5:
输入:nums1 = [2], nums2 = [] 输出:2.00000
提示:
nums1.length == mnums2.length == n0 <= m <= 10000 <= n <= 10001 <= m + n <= 2000-106 <= nums1[i], nums2[i] <= 106原理跟选取第k小元素类似,这里的k表示要求的中位数的位置。每次从两个序列分别取前k/2个数,比较两个第k/2个数的大小,将较小数对应序列的前k/2个数排除,因为这几个数一定包含在要求的中位数之前。下轮再分别取(k-k/2)/2个数,直到k=1;
-
一个技巧:计算序列的中位数,在不确定奇偶时 ,有通式num[mid]=(num[(n+1)/2]+nums[(n+2)/2])/2,n为序列长度。
View Code1 class Solution { 2 public: 3 double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { 4 //第k小元素 5 //每次比较两个余下序列的中间值大小,排除掉其中较小元素的左侧元素,移动指针; 6 //考虑序列各自的奇偶 7 int m=nums1.size(),n=nums2.size(); 8 return (findKth(nums1,0,nums2,0,(m+n+1)/2)+findKth(nums1,0,nums2,0,(m+n+2)/2))/2.0; 9 10 11 } 12 int findKth(vector<int >&nums1,int i,vector<int >&nums2,int j,int k) 13 { 14 if(i>=nums1.size())return nums2[j+k-1]; 15 if(j>=nums2.size())return nums1[i+k-1]; 16 if(k==1){ 17 18 return std::min(nums1[i],nums2[j]); 19 } 20 int mid1=(i+k/2-1>=nums1.size())?INT_MAX:nums1[i+k/2-1]; 21 int mid2=(j+k/2-1>=nums2.size())?INT_MAX:nums2[j+k/2-1]; 22 if(mid1<mid2) 23 return findKth(nums1,i+k/2,nums2,j,k-k/2); 24 return findKth(nums1,i,nums2,j+k/2,k-k/2); 25 } 26 };
5. 最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd" 输出:"bb"
示例 3:
输入:s = "a" 输出:"a"
示例 4:
输入:s = "ac" 输出:"a"
提示:
1 <= s.length <= 1000s仅由数字和英文字母(大写和/或小写)组成
1 class Solution { 2 public: 3 string longestPalindrome(string s) { 4 //最大回文子串 5 //从center向两边延伸元素相等;center为元素或者空格 6 int start=0,end=0; 7 for(int i=0;i<s.length();i++) 8 { 9 int len1=expandCenter(s,i,i);//长度是奇数 10 int len2=expandCenter(s,i,i+1);//长度是偶数 11 int len=(len1>=len2)?len1:len2; 12 if(len>(end-start+1)) 13 { 14 start=i-(len-1)/2; 15 16 end=i+len/2; 17 } 18 } 19 return s.substr(start,end-start+1); 20 21 } 22 int expandCenter(string s,int left,int right) 23 { 24 while(left>=0&&right<s.length()&&s[left]==s[right]) 25 { 26 left--;right++; 27 } 28 return (right-left)-1; 29 } 30 };


浙公网安备 33010602011771号