【Leetcode】題目集:31-40
31.下一個排列(中等)
學會了reverse函式。這個函式是反轉指定的vector容器裡面的資料。給出下標就可使用,無返回值,存在algorithm下。其次還學到了,一定要在腦中先形成一個演算法框架,然後再去動筆寫,如果有必要的話,可以將程式碼思路寫在紙上。
這個題目的思路是首先確定是不是從大到小的排列出來的。如果是的話,直接反轉,我這裡用的是flag;其次再說一下一般的情況,首先要確定的是該序列是要求遞增的。1.首先是從後往前找。找到第一個後一個數字比前一個數字大的(遞增)那個位置,然後標記這個位置。2.再次從後往前找,找到到該位置之前,有第一個數字比他大,則交換。然後再交換位置之後,對第一次標記位置之後的所有數字進行再次倒序交換。最後交換的意義在於,如果第一輪都沒有發現這樣的資料的話,那麼後面的必定都是按照從大到小的排列的,那麼直接對其完全反轉就行了。全排列啊喂!
class Solution { public: void nextPermutation(vector<int>& nums) { bool flag = 0; int k1 = nums.size() - 2 , j = nums.size() - 1; //從後往前找,找到第一個後一個數字比前一個數字大的那個位置// for(int i = nums.size() - 2 ; i >= 0 ; i --){ if(nums[i] < nums[i + 1]){ flag = 1; k1 = i; break; } } //從後往前找,找到在到這個數字之前的那個位置有沒有比它的大的,如果有就交換// if(k1 >= 0){ for(int j = nums.size() - 1 ; j > k1 ; j --) if(nums[j] > nums[k1]){ swap(nums[j] , nums[k1]); break; } } //交換剩餘的東西// if(flag == 1) reverse(nums.begin() + k1 + 1, nums.end()); else{ reverse(nums.begin() , nums.end()); } } };
32.最長有效括號(困難)
學會了字串不屬於基本型別,對於單個的比較就是利用單引號字串。由於字串不屬於基本型別,如果要是入棧的話就直接入棧它的地址下標。還學著利用了動態規劃,但是用的還是不是很好,其實也沒有弄清楚這個到底是什麼意思。還需要整理思路。
首先先考慮特殊情況,這個地方不做特殊說明。以後也會直接忽略,直接說一般的情況。如果遇到一個‘(’,則直接將他彈入到棧中;遇到‘)’的時候,先判斷是否為空,如果為空的話,說明就是“)()”這種情況。第一個永遠匹配不到,那麼就將這個開始的指標向後移動一位。如果不為空的時候,說明裡面有'('這個,將它彈出,隨後考慮這個狀態下的匹配的個數。首先判斷:此時是否為空?如果是的話,說明裡面沒有'('了,那麼也就沒有巢狀的問題,那麼就是直接看目前的‘)’是第幾個,然後和目前的res的數值比較。這個狀態的例子就是“()()()()()”這種。但是如果此時不為空,說明裡面還有巢狀,就是“(()”這種情況,i - v.top()就是目前的長度。注意的是,我們要求的是長度,不是個數。
class Solution {
public:
int longestValidParentheses(string s) {
//魯棒性:0和1 都構不成子串//
if(s.size() == 0 || s.size() == 1){
return 0;
}
//一般情況:用棧//
stack<int> v;
int start = 0 , res = 0;
for(int i = 0 ; i < s.size() ; i ++){
if(s[i] == '('){
v.push(i);
}
else if(s[i] == ')'){
if(v.empty() == 1){
start = i + 1;
}
else{
v.pop();
res = v.empty() == 1 ? max(res , i - start + 1) : max(res , i - v.top());
}
}
}
return res;
}
};
32.搜尋旋轉排序陣列(中等)
學到了:溫習二分法。
這個地方不能用
class Solution {
public:
int search(vector<int>& nums, int target) {
int start = 0 , end = nums.size() - 1 ;
while(start <= end){
if(nums[start] == target){
return start;
}
if(nums[end] == target){
return end;
}
int middle = (start + end) / 2;
if(nums[middle] == target){
return middle;
}
if(nums[start] > nums[middle]){
if(nums[middle] < target && nums[start] > target){
start = middle + 1;
}
else{
end = middle - 1;
}
}
else{
if(nums[middle] > target && nums[start] < target){
end = middle - 1;
}else{
start = middle + 1;
}
}
}
return -1;
}
};
34.在排序陣列中查詢元素的第一個和最後一個位置(中等)
複習二分法。
這個地方就是利用二分法先找到其中某一個元素的位置,然後在這個位置上面左右移動指標找到位置。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> v;
int start = 0 , end = nums.size() - 1;
int k1 = -1 , k2 = -1;
while(start <= end){
int middle = (start + end) / 2;
if(nums[middle] == target){
int i = middle , j = middle;
while(i >= 0 && nums[i] == target){
i --;
k1 = i + 1;//因為每次跳出來之後數字就已經發生變化了,已經減小了一位了,需要補回來。//
}
while(j < nums.size()&& nums[j] == target){
j ++;
k2 = j - 1;
}
v.push_back(k1);
v.push_back(k2);
return v;
}
if(nums[middle] < target){
start = middle + 1;
}
if(nums[middle] > target){
end = middle - 1;
}
}
v.push_back(k1);
v.push_back(k2);
return v;
}
};
35.搜尋插入位置(簡單)
遇到的下標比這個數值大,則選擇這個。最後需要考慮的就是那超過陣列最大的那個。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
for(int i = 0 ; i < nums.size() ; i ++){
if(nums[i] >= target){
return i;
}
}
return nums.size();
}
};