LeetCode—31(下一个排序)
方法:求下一个排列顺序,如果给定数组是降序,则说明是全排列的最后一种情况。则说明是全排列的最后一种情况,则下一个排列就是最初始情况。其余情况理解:
如有一个数组:
127431
1 2 7 4 3 1
127431 则下一个排列为:
131247
131247
131247
从末尾往前看,数字逐渐变大,到了2时才减小的,然后我们再往后找一个比2大的数字,是3,那么我们交换2和3,此时再把3后面的数字转置一下即可。
C++代码:
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int n = nums.size(),i = n - 2,j = n - 1;
while(i>=0 && nums[i]>=nums[i+1]) --i;
if(i>=0){
while(nums[j]<=nums[i]) --j;
swap(nums[i],nums[j]);
}
reverse(nums.begin()+i+1,nums.end());//是交换i后面的序列。
}
};
LeetCode—32(最长有效括号)
方法一:借助栈的来求解,需要定义start变量来记录合法括号串的起始位置,遍历字符串。若遇到 ‘(’ 则压入栈,如果遇到 ‘)’
若栈为空,则下一个坐标记录start。若栈不为空,则取出栈顶元素。若此时栈为空,则max(res,i-start+1),若不为空,则max(res,i-栈顶元素坐标)。
C++代码:
class Solution {
public:
int longestValidParentheses(string s) {
int res = 0,start = 0;
stack<int> m;
for(int i=0;i<s.size();++i){
if (s[i] == '(') m.push(i);
else if(s[i] == ')'){
if(m.empty()) start = i + 1;
else{
m.pop();
res = m.empty() ? max(res,i-start+1) : max(res,i-m.top());
}
}
}
return res;
}
};
方法二:动态规划Dynamic Programming的解法(待学习)
LeetCode—33(搜索旋转排序数组)
方法一:限定了时间为
O
(
l
o
g
n
)
O(logn)
O(logn),那么就考虑二分法搜索,但是难点是得寻找原数组在哪里旋转了。对于旋转情况分析:
我们知道二分法的关键在于获得了中间数后,判断下面要搜索左半端还是右半段。通过上面的规律可以发现。若中间的数小于最右边的数,则右半段是有序的。若中间的数大于最右边数,则左半端是有序的。剩下的就是二分法的思想。
C++代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {//差个等于号 结果完全不一样
int mid = left + (right - left) / 2;
if (nums[mid] == target) return mid;
else if (nums[mid] < nums[right]) {
if (nums[mid] < target && nums[right] >= target) left = mid + 1;
else right = mid - 1;
} else {
if (nums[left] <= target && nums[mid] > target) right = mid - 1;
else left = mid + 1;
}
}
return -1;
}
};
LeetCode—34(在排序数组中查找元素的第一个和最后一个位置)
方法一:首先对原数组使用二分查找法,找出其中一个目标值的位置,然后向两边搜索找出起始和结束的位置。(但是这种方法在最坏的情况下会变成
O
(
n
)
O(n)
O(n),即数组中的数字全为目标值。)
方法二:使用二分法查找法,第一次找到左边界,第二次调用找到右边界即可。
C++代码:
class Solution {
public://报错代码(不知道为啥)
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> res(2, -1);
int left = 0, right = nums.size() - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) left = mid + 1;
else right = mid;
}
if (nums[right] != target) return res;
res[0] = right;
right = nums.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] <= target) left = mid + 1;
else right= mid;
}
res[1] = left - 1;
return res;
}
};
LeetCode—35(搜索插入位置)
方法:用二分搜索法优化时间复杂度。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
if (nums.back() < target) return nums.size();
int left = 0,right = nums.size() - 1;
while(left < right){
int mid = left + (right - left)/2;
if(nums[mid] == target) return mid;
else if(nums[mid] < target) left = mid + 1;
else right = mid;
}
return right;
}
};