31 Next Permutation
STL源码剖析中就有这道题的思路
32 longest valid parentheses (hard)
思路1:用stack实现。当i为左括号时,将i入栈。如果i为右括号时:栈顶元素对应的s为左括号,记录accout=i-stack.top();如果为左括号,则讲i入栈
思路2:动态规划
初始化:dp[i]=0 i=0-len-1
从i=len-2开始 if(dp[i]==’(’ && i+dp[i+1]+1
int longestValidParentheses(string s) {
int len = s.length();
if(len<2)
return 0;
int max = 0;
int *dp = new int[len];
for(int k = 0;k<len;k++)//把辅助数组清空,存储为0
dp[k] = 0;
for(int i = len-2;i>=0;i--)
{
if(s[i] == '(')//只对左括号处理,右括号在数组中存储为0
{
int j = i+1+dp[i+1];//计算与当前左括号匹配的右括号的位置。可能存在也可能不存在
if(j<len && s[j] == ')')//确保位置不能越界
{
dp[i] = dp[i+1] + 2;//找到了相匹配的右括号,当前数组中存储的最长长度是它后一个位置加2,后一个位置可能存储长度是0
if(j+1<len)//这是连接两个子匹配的关键步骤
dp[i] += dp[j+1];//在j的后面可能已经存在连续的匹配,要记得加上。dp[j+1]存储了以j+1开始的匹配
}
if(dp[i]>max)
max = dp[i];//更新最长长度
}
}
return max;
}
33 search in rotated sorted array(hard)
这道题剑指offer出现过类似的题目,这道题是个简化的版本,不考虑元素存在重复的情况
思路,用二值查找法
int search(vector<int>&A,int target)
{
int n=A.size();
int low=0;
int high=n-1;
while(low<=high){
int mid=low+(high-low)/2;
if(A[mid]==target)return mid;
if(A[mid]<A[high])
{
if(A[mid]<target && A[high]>=target )
low=mid+1;
else
high=mid-1;
}
else
{
if(A[mid]>target &&A[low]<=target)
high=mid-1;
else
low=mid+1;
}
}
return -1;
}
34 Search for a Range(medium)
在一个排序的数组中,找到给点数在数组中一样的数的下标范围
思路:用二分查找,与普通二分查找差异处在于 nums[mid]==target 并没有结束。而是要找到low于mid之间最前面出现的target下标,找到high与mid之间最后面出现的target下标
//low
int tmplow=low,tmphigh=mid-1,tmpmid;
while(tmplow<=tmphigh)
{
tmpmid=(tmplow+tmphigh)/2;
if(nums[tmpmid]==target)
tmphigh=tmpmid-1;
else
tmplow=tmpmid+1;
}
result[0]=tmplow;
//high
tmplow=mid+1;
tmphigh=high;
while(tmplow<=tmphigh)
{
tmpmid=(tmplow+tmphigh)/2;
if(nums[tmpmid]==target)
tmplow=tmpmid+1;
else
tmphigh=tmpmid-1;
}
result[1]=tmphigh;
35 search insert position
在常规的二分查找的基础上,增加以下的代码即可
if(nums[mid]>target)
{
if(mid==0)
return 0;
else
return mid;
}
else
return mid+1;
36 valid Sudoku
这道题是简单的,只要在3个条件下判断即可(3*3的正方形填充的数字是否要重复的元素,同理去判断每行,每列)只要有重复的元素出现,则返回false
37 sudoku solver (hard)
这道题采用回溯法。每个格子没有存数,则每尝试一个数,先判断是否符合条件(检查每行每列,3*3元素是否存在跟填入的数相等的),符合条件,则进行下一个元素。。。。如果下一个元素返回false,当前元素再尝试一个新值
38 count and say (easy)
这道题在弄懂题目的含义以后,还是很简单的。就是一种新的理解读数方式。讲每个数独立看待,如果有n个一样的数组digit连续出现则用ndigit表示。1—>11 11—>21 111->31
39 combination sum
这道题的思想就是回溯的思想,这种思想在leetcode前面的题目出现过。基本思路进行下一层的遍历。。。返回到当层时,变量要恢复到以前的状态
40 combination sum II
这一题在前一题的基础要多一些考虑。要考虑多个重复的数字的情况下,要如何组合。多个重复的数字为number,重复k次,则要考虑加入1-k次number的结果
41 first missing positive (hard)
这道题的思路就是,通过交换实现,每个数字要对应于一位置。数字i存放在位置i-1,对于不符合条件的数字进行对换。最后,通过一次遍历,不满足条件nums[i]!=i+1,return i+1;
这种解题思路,很多题目中都可以运用的到的
42 trapping rain water (hard)
思路:先找到最大值。然后从两端向中心的最大值遍历。在遍历过程中,每个柱子与遍历的目前最大值比较,如果小于它,面积加上两者之间的差值,如果大于它,则更新目前的最大值
43 multiply (medium)
这道题就是大数相乘
利用我们平时进行乘法的思想运算,从两个数的最低位进行乘法,乘法的结果要加上上次的进位
string multiply(string num1, string num2) {
if (!num1.compare("0") || !num2.compare("0")) return "0";
string num;
int len1=num1.length();
int len2=num2.length();
num.resize(len1+len2);
int addon=0;
for(int i=0; i<len1+len2; i++)
{
num[i]='0';
}
for(int i=len1-1; i>=0; i--)
{
addon=0;
for(int j=len2-1; j>=0; j--)
{
int tmp=num[i+j+1]-'0'+(num1[i]-'0')*(num2[j]-'0')+addon;
addon=tmp/10;
num[i+j+1]=tmp%10+'0';
}
num[i]+=addon;
}
if(num[0]=='0')//只可能最高位为0
{
num.erase(num.begin());
}
return num;
}
44wildcard matching (hard)
45 jump game II(hard)
比较目前能够到达的最远位置,到达最远位置后,要更新step,即++step,每次遍历更新增加一步能够到达的最远位置
int jump(vector<int>& nums) {
int n=nums.size();
if(n<=1)
return 0;
int step = 0;
int curMax = 0;
int curRch = 0;
for(int i = 0; i < n; i ++)
{
if(curRch < i)
{
step ++;
curRch = curMax;
}
curMax = max(curMax, nums[i]+i);
}
return step;
}
46 permutations (medium)
就是STL中的思路
47 permutations II (medium)
与上题一样
48rotate image(medium)
i=1:n/2
j=1:(n+1)/2
旋转的规律:(i,j)–>(n-1-j,i)
(n-1-j,i)–>(n-1-i,n-1-j)
(n-1-i,n-1-j)–>(j,n-1-i)
(j,n-1-i)–>(i,j)
49 Group anagrams (medium) 看看
用map
map<string, vector<string>> hashMap;
for(auto &v : strs) {
string tmp(v);
sort(tmp.begin(), tmp.end());
hashMap[tmp].push_back(v);
}
vector<vector<string>> result(hashMap.size());
int k = 0;
for(auto it = hashMap.begin(); it != hashMap.end(); ++it, ++k) {
result[k].swap(it->second);
sort(result[k].begin(), result[k].end());
}
return result;
50 pow(x,n) (medium)
用递归思想,result=pow(x,n/2) result=result^2; n为奇数 result=result*x 偶数 result=result
进行运算,需要考虑的特殊情况。x为0,1,-1. n为0. n<0,尤其为INT_MIN。因为负数可以比正数多表示一个数,所有表示为pow(INT_MAX)*x
51 # N-Queens (hard)
用一个大小为N的数组,存储每行Q的位置
最后遍历到row==N时,将结果存入到vector中
判断是否符合条件
bool check(int row, int* place)
{
for (int i = 0; i < row; ++i)
{
int diff = abs(place[i] - place[row]);
if (diff == 0 || diff == row - i)
return false;
}
return true;
}
52 N-Queens II (hard)
与上一题类似
53 Maximum subarray (medium)
这道题可以用贪心算法的思想,tempsum与maxvalue比较,如果大于则更新maxvalue。如果 tempsum<0,则令tempsum=0. 最后返回maxvalue
54 spiral Matrix (medium)
这道题剑指offer中也有一样的题目。思路就是每次进行循环就是输出了2行2列的矩阵。用一个i表示进行第几次循环,结束条件也就清楚了
一般情况下,一次循环可分割为4次操作。但是要考虑特殊情况。进行一次,两次,三次情况
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> result;
int m=matrix.size();
if(m==0)
return result;
int n=matrix[0].size();
if(n==0)
return result;
int i=0;
while (m-2*i>0 && n-2*i>0)
{
for (int j=i;j<n-i;++j)
{
result.push_back(matrix[i][j]);
}
for (int j=i+1;j<m-i;++j)
{
result.push_back(matrix[j][n-i-1]);
}
if (m-i-1>i)
{
for (int j=n-i-2;j>=i;--j)
{
result.push_back(matrix[m-i-1][j]);
}
}
if (i!=n-i-1)
{for (int j=m-i-2;j>i;--j)
{
result.push_back(matrix[j][i]);
}
}
++i;
}
return result;
}
55 Jump Game (medium)
这道题采用贪心思想。从头开始遍历。如果maxstep==0,return false maxstep=–maxstep>nums[i] ?maxstep, nums[i];
56 merge intervals (hard)
先对vector根据start大小进行排序,排序结束后,进行合并
57 insert interval (hard)
一共分三种情况,插入的位置在头部,尾部,中间位置
中间位置的情况要找到插入的地方,要确定pre,last坐标
vector<Interval> insert(vector<Interval>& intervals, Interval newInterval) {
int len=intervals.size();
vector<Interval> result;
if(len==0)
{
result.push_back(newInterval);
return result;
}
if(newInterval.end<=intervals[0].end)
{
if (newInterval.end>=intervals[0].start)
{
intervals[0].start=min(intervals[0].start,newInterval.start);
}
else
{ intervals.insert(intervals.begin(),newInterval);
}
return intervals;
}
if (newInterval.start>=intervals[len-1].start)
{
if (newInterval.start<=intervals[len-1].end)
{
intervals[len-1].end=max(intervals[len-1].end,newInterval.end);
}
else
{
intervals.push_back(newInterval);
}
return intervals;
}
int pre=-1;
int flag=0;
for(int i=0;i<len;++i)//确定pre的位置
{
if(intervals[i].end<newInterval.start)
{
pre=i;
result.push_back(intervals[i]);
}
else
break;
}
int last=pre;
int i;
for(i=pre+1;i<len;++i)//确定last位置
{
if(intervals[i].start<=newInterval.end)
last=i;
else
break;
}
if (pre!=last)
{ newInterval.start=min(intervals[pre+1].start,newInterval.start); newInterval.end=max(intervals[last].end,newInterval.end);
}
result.push_back(newInterval);
for(i=last+1;i<len;++i)
result.push_back(intervals[i]);
return result;
}
58 length of last word (easy)
这道题很简单,从后面往前遍历。先找到第一个非空格的位置,再接着找到空格的位置即可
59 spiral matrix II (medium)
这道题与54题类似,可以参照那一题的思路进行
60 permutation sequence (medium)
假设有n个元素,第k个permutation是a1, a2, a3, ….. …, an
那么这里,我们把a1去掉,那么剩下的permutation为
a2, a3, …. …. an, 共计n-1个元素。 n-1个元素共有(n-1)!个排列,那么这里就可以知道
设变量K1 = k
a1 = K1 / (n-1)!// 第一位的选择下标
同理,a2的值可以推导为
K2 = K1 % (n-1)!
a2 = K2 / (n-2)!
。。。。。
K(n-1) = K(n-2) /2!
a(n-1) = K(n-1) / 1!
an = K(n-1)
string getPermutation(int n, int k) {
int sum=1;
string str="123456789";
for(int i=1;i<=n;i++)
sum=sum*i;
k--;
string r="";
for(int i=n;i>=1;i--)
{
sum=sum/i;
int pos=k/sum;
r+=str[pos];
k=k%sum;
str.erase(pos,1);
}
return r;
}