劍指offer刷題

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。

/**
*  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;

    }
};
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==uploading.4e448015.gif轉存失敗重新上傳取消wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

八 爬臺階

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;
    }
};
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==uploading.4e448015.gif轉存失敗重新上傳取消wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

九變態爬樓梯

【遞歸】

  • 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);
        }

    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章