1 二維數組找target 2/27
題目描述:在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
思路:
- 習慣使用雙指針,然後嵌套循環;時間O(nlogn) 空間O(n);
- 如果行和列有一個較大,選擇循環較小的那個(待解決);
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int row = (int)array.size();
int col = (int)array[0].size();
for(int i = 0; i < row; i++){
int left = 0, right = col - 1;
while(left <= right){
int middle = left + (right - left)/2;
if(array[i][middle] == target) return true;
else if(array[i][middle] > target) right = middle - 1;
else left = middle + 1;
}
}
return false;
}
};
//或者
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int row = array.size();
int col = array[0].size();
for(int i = 0; i < col; i++){
int left = 0, right = row - 1;
while(left<= right){
int middle = left + (right - left)/2;
if(array[middle][i] == target) return true;
else if(array[middle][i] < target) left = middle + 1;
else right = middle - 1;
}
}
return false;
}
};
二 替換空格
- 雙指針,從後往前遍歷覆蓋原字符串
【易錯】錯誤出在‘\0’,無語
參考:https://www.cnblogs.com/codingmengmeng/p/5857143.html
class Solution {
public:
void replaceSpace(char *str,int length) {
if(str == NULL && length <= 0) return;
int oldLen = 0;
int blankLen = 0;
for(oldLen = 0; str[oldLen] != '\0'; oldLen++){
if(str[oldLen] == ' ') blankLen++;//遍歷字符串,計數空字符數
}
int newLen = oldLen + blankLen*2;//計數新字符數
if(newLen > length) return;//若新字符串長度超過給定數組長度,返回空
str[newLen] = '\0';//新字符串末尾加\0
int p1 = oldLen - 1, p2 = newLen - 1;//設置快慢指針
//p1指向原字符串,p2指向新字符串
while(p1 >= 0 && p2 > p1){//從後往前覆蓋掉原字符串
if(str[p1] == ' '){//找到空格,新字符串加字符
str[p2--] = '0';
str[p2--] = '2';
str[p2--] = '%';
}else{
str[p2--] = str[p1];//不是空字符,則複製原字符
}
p1--;
}
}
};
三 鏈表翻轉(從尾到頭打印鏈表)2/28
題目表述:輸入一個鏈表,按鏈表從尾到頭的順序返回一個ArrayList。
- 1 參考https://blog.csdn.net/howe1233/article/details/88371887,利用reverse函數
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) :
* val(x), next(NULL) {
* }
* };
*/
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;//新建一個vector
while(head != NULL){
res.push_back(head->val);//將鏈表放進res
head = head -> next;
}
reverse(res.begin(), res.end());//reverse翻轉res
return res;//返回翻轉後的值
}
};
- 2 棧的先進後出
參考https://www.cnblogs.com/zhonglixunta/articles/9523707.html
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) :
* val(x), next(NULL) {
* }
* };
*/
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;//新建vector存放結果
stack<int> array;//新建棧
ListNode * p = head;
while(p != NULL){//將鏈表存放入堆棧
array.push(p -> val);
p = p -> next;
}
int len = array.size();
for(int i = 0; i < len; i++){
res.push_back(array.top());//將棧中的數據pop出
array.pop();
}
return res;
}
};
六 旋轉數組的最小元素
題目描述:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。
輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。
例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。
NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。
思路:
像leetcode裏 search in rotated array2 在旋轉後的的數組中尋找目標數字;
- 使用二分法;
有一個特殊情況:當數組中有【重複數字】,要忽略重複數字,再進入判斷,即 mid = left; /mid = right; 則right--;
參考:https://www.cnblogs.com/grandyang/p/4040438.html
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
int left = 0, right = (int)rotateArray.size() - 1;
while(left < right){//注意是<,否則重複比較
int mid = left + (right - left) / 2;
if(rotateArray[mid] > rotateArray[right]) left = mid + 1;//左半段有序,比如{3423}
else if(rotateArray[mid] < rotateArray[right]) right = mid;//右半段有序,但是mid可能就是最小值,比如{3123},要注意這裏的邊界
else right--;//刪除重複
}
return rotateArray[right];
}
};
經過查找和和LeetCode上153,154是一樣的。只不過153的數組元素是不重複的,154則允許數組有重複元素。
這裏直接要求輸入的是非遞減排序的數組,所以和154題是一樣的。
參考:https://www.cnblogs.com/silentteller/p/11832273.html
- 分治法, 局部最小, 遞歸
【高亮】【注意邊界】
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.empty()) return 0;
return find(rotateArray, 0, rotateArray.size() - 1);
}
//分割成左右兩個數組,尋找有序的子數組中的最小值,如果子數組無序,則繼續分割;
//判斷數組是否有序:數組左邊界小於右邊界則有序
//當左右值相同,不能認爲數組內元素值都相同,要繼續分割,知道左邊值 < 右邊值
int find(vector<int>& nums, int l, int r){
if(nums[l] < nums[r] || l == r) return nums[l];
int mid = l + (r - l) / 2;
return min(find(nums, l, mid), find(nums, mid + 1, r));//
}
};
七 斐波那契數列
題目描述:大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項爲0)。
- 需要注意的是這裏起始項f(1) = 1, f(2) = 1, f(3) = 2;因此循環終止條件爲n-1次
class Solution {
public:
int Fibonacci(int n) {
if(n == 0) return 0;//考慮特殊情況,第0項
int pre = 0;//前指針
int cur = 1;//後指針
for(int i = 1; i < n; i++){
int temp = cur;//臨時指針保存當前的後指針
cur = cur + pre;//當前指針 = 前兩項之和
pre = temp;//更新前指針爲臨時指針,前指針移到上一個後指針的位置上
}
return cur;
}
};
轉存失敗重新上傳取消八 爬臺階
leetcode裏寫過 【動態規劃】【斐波那契】
- 需要注意的是這裏起始項f(1) = 1, f(2) = 2, f(3) = 3;因此【循環終止條件是n次】
class Solution {
public:
int jumpFloor(int number) {
int pre = 0;
int cur = 1;
for(int i = 1; i <= number; i++){//注意這裏<=,可以由前三項測試得知
int temp = cur;
cur = cur + pre;
pre = temp;
}
return cur;
}
};
轉存失敗重新上傳取消九變態爬樓梯
【遞歸】
- f(1) = 1, f(2) = 2, f(3) = 4, f(4) = 8, f(5) =16; f(n) = 2^n;
class Solution {
public:
int jumpFloorII(int number) {
if(number == 1) return 1;
if(number == 2) return 2;
return 2 * jumpFloorII(number - 1);
}
};
十 矩形覆蓋
雖然我知道是斐波那契數列,但是我沒看懂https://blog.csdn.net/qq_21583077/article/details/97644291
class Solution {
public:
int rectCover(int number) {
if(number == 0) return 0;
if(number == 1) return 1;
if(number == 2) return 2;
for(int i = 0; i < number; i++){
return rectCover(number - 1) + rectCover(number - 2);
}
}
};