两数之和
1. 两数之和 - 力扣(LeetCode) (leetcode-cn.com)
解法1:暴力解法(O ( n 2 ) O(n^2) O ( n 2 ) )
先在这个数取出位置i的数字,然后选择j=i+1,判断两个数字相加是否为目标数字,是则返回,否则j++,j遍历完就i++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution {public : vector<int > twoSum (vector<int >& nums, int target) { vector<int > res; for (int i = 0 ;i<nums.size ();i++) for (int j = i+1 ;j<nums.size ();j++){ if (nums[i]+nums[j] == target) { res.push_back (i); res.push_back (j); return res; } } return res; } };
解法2:哈希表存储所有数字(O ( n ) O(n) O ( n ) )
先用哈希表存入所有vector中的数字,以数字为键,下标为值。因为不存在的数字默认为0,所以存入下标的时候要+1
然后遍历每一个数字,看一下目标减去这个数字是否存在,存在则返回该值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution {public : vector<int > twoSum (vector<int >& nums, int target) { unordered_map<int ,int > mp; for (int i = 1 ;i<=nums.size ();i++){ mp[nums[i-1 ]] = i; } for (int i = 0 ;i<nums.size ();i++){ if (mp[target-nums[i]]&&mp[target-nums[i]]!=i+1 ) { return {i,mp[target-nums[i]]-1 }; } } return {}; } };
两数相加
2. 两数相加 - 力扣(LeetCode) (leetcode-cn.com)
建议参考大数相加模板,有手就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution {public : ListNode* addTwoNumbers (ListNode* l1, ListNode* l2) { ListNode head = ListNode (); ListNode* p = &head; int t = 0 ; while (l1 != nullptr || l2 != nullptr ){ if (l1){t+=l1->val;l1 = l1->next;} if (l2){t+=l2->val;l2 = l2->next;} p->next = new ListNode (t%10 ); p = p->next; t/=10 ; } if (t)p->next = new ListNode (t); return head.next; } };
无重复字符的最长子串
3. 无重复字符的最长子串 - 力扣(LeetCode) (leetcode-cn.com)
子串:连在一起的叫子串
子序列:可以不连在一起的叫子序列
定义目标串的起点和终点都在最初的位置,然后开始向后遍历终点,终点位置如果没有出现在哈希表里,就将当前位置的字符作为key,value为end+1放到哈希表中,每次更新最长的距离为num = max(num,end-start+1)
,如果当前字符已经出现过了,就确定是在start之前还是之后出现的,更细一下start的位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution {public : int lengthOfLongestSubstring (string s) { unordered_map<char ,int > mp; int num = 0 ,start,end; for (start = 0 ,end = 0 ;end<s.size ();end++){ if (mp[s[end]]){ start = max (start,mp[s[end]]); } num = max (num,end-start+1 ); mp[s[end]] = end+1 ; } return num; } };
寻找两个正序数的中位数
4. 寻找两个正序数组的中位数 - 力扣(LeetCode) (leetcode-cn.com)
解法1:暴力做法,将两个vector统合成一个vector,然后使用sort进行排序,根据数据的奇偶判断中位数(O ( ( N + M ) l o g ( N + M ) ) O((N+M)log(N+M)) O (( N + M ) l o g ( N + M )) )
1 2 3 4 5 6 7 8 9 10 class Solution {public : double findMedianSortedArrays (vector<int >& nums1, vector<int >& nums2) { for (int i = 0 ;i<nums2.size ();i++) nums1.push_back (nums2[i]); sort (nums1.begin (),nums1.end ()); if (nums1.size ()%2 )return nums1[nums1.size ()/2 ]; else return (nums1[nums1.size ()/2 ]+nums1[nums1.size ()/2 -1 ])/2.0 ; } };
解法2:递归
假设两个数组的长度为n,m,那么只要找到k = n + m 2 k=\frac{n+m}2 k = 2 n + m 位置的数字就可以了,递归的做法就是每次看一下k 2 < k \frac k2<k 2 k < k 在两个数组中的数字,如果nums1[k/2]>nums2[k/2]
,说明nums2中前k 2 \frac k2 2 k 个数字都不是答案,可以舍弃。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution {public : double findMedianSortedArrays (vector<int >& nums1, vector<int >& nums2) { int tot = nums1.size ()+nums2.size (); if (tot%2 ==0 ){ int left= find (nums1,0 ,nums2,0 ,tot/2 ); int right = find (nums1,0 ,nums2,0 ,tot/2 +1 ); return (left+right)/2.0 ; }else return find (nums1,0 ,nums2,0 ,tot/2 +1 ); } int find (vector<int > &nums1,int i,vector<int >&nums2,int j,int k) { if (nums1.size ()-i>nums2.size ()-j)return find (nums2,j,nums1,i,k); if (k==1 ){ if (nums1.size ()==i)return nums2[j]; else return min (nums1[i],nums2[j]); } if (nums1.size ()==i)return nums2[j+k-1 ]; int si = min ((int )nums1.size (),i+k/2 ),sj = j+k/2 ; if (nums1[si-1 ]>nums2[sj-1 ]) return find (nums1,i,nums2,sj,k-(sj-j)); else return find (nums1,si,nums2,j,k-(si-i)); } };
最长回文子串
5. 最长回文子串 - 力扣(LeetCode) (leetcode-cn.com)
遍历每一个点,以他作为中心,然后向两边拓展,判断回文。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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; } };
Z字形变换
6. Z 字形变换 - 力扣(LeetCode) (leetcode-cn.com)
解法一 :我的解法
根据观察Z型结构坐标的数据,令当前位置为pos,当前行数为line,规定行数为num
Z型的两个竖线之间的间隔cnt=2*(num-1)
,
比如字符串行为4时,0号为第一条竖线的第一个位置,那么第二条竖线要经过1,2,3,4,5后才能到达
第二条竖线与第一条竖线的距离为6 = 2*(4-1)=cnt
当我们当前位置pos位于竖线上时,即(pos-line)%cnt==0
时,并且他还不是最后一行line != num-1
这时候他就要向下走到下一个竖线的对应位置,向下的计算公式为pos+(num-line-1)*2
。(可以自己带数字进去试试)
不然的话,就要向上走到达下一个位置,向上的计算公式为pos+2*line
遍历每一行,然后把对应的位置pos的位置添加到结果中就可以得到答案了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution {public : int up (int pos,int line) { return pos+2 *line; } int down (int pos,int num,int line) { return pos+(num-line-1 )*2 ; } string convert (string s, int numRows) { if (numRows==1 )return s; string res; for (int i = 0 ; i < numRows; i++) { int pos = i, cnt = (numRows - 1 ) * 2 ; while (pos < s.size ()) { res += s[pos]; bool inlines = (pos - i) % cnt == 0 ; pos = !inlines || i == numRows - 1 ? up (pos, i) : down (pos, numRows, i); } } return res; } };
解法2 :别人的解法
第一行和最后一行都是公差为2n-2
的等差数列
其他行在Z型的竖线上的数字都是公差为2n-2
的等差数列,在Z型斜线上的数字也是公差为2n-2
的数字
Z型的第一列竖线与对应的行数匹配,在第i行中第一个斜线上的数a与改行第一个竖线上的数b有关系b = 2n-2-i
然后遍历每一行,根据不同的情况,分别计算每一行的等差数列即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution {public : string convert (string s, int numRows) { if (numRows==1 )return s; string res; int n = numRows; for (int i = 0 ;i<numRows;i++){ if (i==0 ||i==numRows-1 ){ for (int j = i;j<s.size ();j+= 2 *n-2 ) res += s[j]; }else { for (int j = i,k = 2 *n-2 -i;j<s.size ()||k<s.size ();j+=2 *n-2 ,k+=2 *n-2 ){ if (j<s.size ())res+=s[j]; if (k<s.size ())res+=s[k]; } } } return res; } };
解法3 :(建议忽略)暴力解法,直接模拟Z型排列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Solution {public : string convert (string s, int numRows) { if (1 ==numRows) return s; int cnt[1010 ][1010 ]; int x=0 ,y=0 ,num=0 ,flag=1 ; for (int i = 0 ;i<s.size ();i++){ cnt[x][y] = i+1 ; num++; if (flag){ if (num == numRows){ num = 1 ; x -= 1 ,y+=1 ; flag = 0 ; }else x+=1 ; }else { if (num==numRows){ num = 1 ; x+=1 ; flag = 1 ; }else x-=1 ,y+=1 ; } } string res; for (int i = 0 ;i<1010 ;i++) for (int j = 0 ;j<1010 ;j++) if (cnt[i][j]) res+=s[cnt[i][j]-1 ]; return res; } };
整数反转
7. 整数反转 - 力扣(LeetCode) (leetcode-cn.com)
有手就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution {public : int reverse (int x) { int res = 0 ; while (x){ if (res>0 &&res>(INT_MAX-x%10 )/10 )return 0 ; if (res<0 &&res<(INT_MIN-x%10 )/10 )return 0 ; res = res*10 +(x%10 ); x/=10 ; } return res; } };
字符串转换整数(atoi)
8. 字符串转换整数 (atoi) - 力扣(LeetCode) (leetcode-cn.com)
和上一题差不多的思路,就是要做一下字符串前处理而已
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution {public : int myAtoi (string s) { int pos = 0 ; while (pos<s.size ()&&s[pos]==' ' )pos++; if (pos==s.size ())return 0 ; int flag = 1 ,res = 0 ; if (s[pos]=='-' )flag = -1 ,pos++; else if (s[pos]=='+' )pos++; while (pos<s.size ()&&s[pos]>='0' &&s[pos]<='9' ){ int x = s[pos]-'0' ; if (flag==1 &&res>(INT_MAX -x)/10 )return INT_MAX; if (flag==-1 &&-res<(INT_MIN+x)/10 )return INT_MIN; if (-res*10 -x==INT_MIN) return INT_MIN; res = res*10 +x; pos++; } return res*flag; } };
回文数
9. 回文数 - 力扣(LeetCode) (leetcode-cn.com)
解法1 :我的方法:
想办法获取数字前后两头的数字,然后进行比较。获取方式见代码。
优化了一下,开了个数组存一下10的次方数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution {public : long long pow10[11 ]; bool isPalindrome (int x) { if (x<0 )return false ; pow10[0 ] = 1 ; for (int i = 1 ;i<11 ;i++) pow10[i] = pow10[i-1 ]*10 ; int cnt = 0 ,tmp = x; while (tmp){ cnt++; tmp/=10 ; } int left = 0 ; for (int i = 1 ,j = cnt-1 ;i<=j;i++,j--){ int l = x/pow10[j]-left,r = x%pow10[i]/pow10[i-1 ]; if (l!=r)return false ; left = (left+l)*10 ; } return true ; } };
解法2 :转成字符串(虽然题中的进阶不能这么干)
1 2 3 4 5 6 7 8 class Solution {public : bool isPalindrome (int x) { if (x<0 )return false ; string s = to_string (x); return s == string (s.rbegin (),s.rend ()); } };
解法3 :直接从右向左取出每一位,然后把这一位和反转数变量乘10再相加,最后得到结果如果和目标相同就是回文数(是我笨比了)
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution {public : bool isPalindrome (int x) { if (x<0 )return false ; int y = x; long long res = 0 ; while (x){ res = res * 10 + x%10 ; x/=10 ; } return res == y; } };
正则表达式匹配
10. 正则表达式匹配 - 力扣(LeetCode) (leetcode-cn.com)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution {public : bool isMatch (string s, string p) { int n=s.size (),m=p.size (); s = " " +s,p=" " +p; vector<vector<bool >> f (n+1 ,vector<bool >(m+1 )); f[0 ][0 ] = true ; for (int i = 0 ;i<=n;i++) for (int j = 1 ;j<=m;j++){ if (j+1 <=m&&p[j+1 ]=='*' )continue ; if (i&&p[j]!='*' ){ f[i][j] = f[i-1 ][j-1 ]&&(s[i]==p[j]||p[j]=='.' ); }else if (p[j]=='*' ){ f[i][j] = f[i][j-2 ] || (i && f[i-1 ][j]&&(s[i]==p[j-1 ]||p[j-1 ]=='.' )); } } return f[n][m]; } };
盛最多水的容器
11. 盛最多水的容器 - 力扣(LeetCode) (leetcode-cn.com)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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; } };
转换罗马数字
12. 整数转罗马数字 - 力扣(LeetCode) (leetcode-cn.com)
这题要找规律,如图,从这里看到,我们个位十位百位千位的数字都能用下述字母表示,暴力一点就可以将下表全部存起来,然后通过查字典的方式就可以获取所有组合比如1234 = 1000+200+30+4=M+CC+XXX+IV=MCCXXXIV
但是这里可能不需要存这么多,存圈出来的数据,然后遍历字典中的值,如果目标数字大于当前选中的符号数字,就直接减去这个数字,然后将符号添加到结果中,否则,就选择更小的符号数字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution {public : string intToRoman (int num) { int nums[] = {1 ,4 ,5 ,9 ,10 ,40 ,50 ,90 ,100 ,400 ,500 ,900 ,1000 }; string roman[] = {"I" ,"IV" ,"V" ,"IX" ,"X" ,"XL" ,"L" ,"XC" ,"C" ,"CD" ,"D" ,"CM" ,"M" }; int cnt = 12 ; string res; while (num){ if (num>=nums[cnt]){ res += roman[cnt]; num-=nums[cnt]; }else { cnt--; } } return res; } };
最长公共前缀
14. 最长公共前缀 - 力扣(LeetCode) (leetcode-cn.com)
同时遍历每一个字符串某个位置的字符,如果相等就继续遍历,不等直接返回
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution {public : string longestCommonPrefix (vector<string>& strs) { char now; bool flag = true ; int k=0 ; while (flag){ if (k>=strs[0 ].size ()){flag = false ;break ;} now = strs[0 ][k]; for (int i = 1 ;i<strs.size ();i++){ if (k>=strs[i].size ()||strs[i][k]!=now){ flag = false ; break ; } } if (flag)k++; } return strs[0 ].substr (0 ,k); } };
三数之和
15. 三数之和 - 力扣(LeetCode) (leetcode-cn.com)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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; } };
end