其他分享
首页 > 其他分享> > 剑指offer

剑指offer

作者:互联网

目录

数据结构-数组

数组中重复的数字

这个绝对不是简单题,是与面试官交流的问题

范围在\(0...n-1\)所以如果没出现重复的数,重排之后是按照0~n-1这样排序的。

这题简单的方法是直接排序,这样时间复杂度\(O(nlogn)\)

但是可以更优化一下,如果当前位置\(i\)不等于\(a[i]\),就让位置\(i\)与位置\(a[i]\)的值交换

这样每个数最多交换两次,第一次交换到\(i\)位置,第二次交换回到正确位置

如果\(a[i]==a[a[i]]\),那么说明找到重复的了

时间复杂度 \(O(n)\) 空间复杂度\(O(n)\)

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        int ans = -1;
        for(int i = 0;i < nums.size();++i){
            while(i!=nums[i]){
                if(nums[nums[i]] == nums[i]) {
                    ans = nums[i];
                    break;
                }
                else swap(nums[i],nums[nums[i]]); 
            }
            if(ans != -1) break;
        }
        return ans;
    }
};

二维数组中的查找

第一次我直接用二分

但是有更简单的做法,如果站在右上角看的话就是一个查找二叉树

时间复杂度\(O(logn)\)

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        bool isFound = 0;
        if(matrix.empty()) return 0;
        int m = matrix[0].size(),n = matrix.size();
        int i = 0,j = m - 1;
        while(i < n && j != -1){
            if(matrix[i][j] == target){
                isFound = 1;
                break;
            }
            if(matrix[i][j] > target){
                --j;
            }
            else if(matrix[i][j] < target){
                ++i;
            }
        }
        return isFound;
    }
};

这题更重要的是测试样例

替换空格

如果是要求时间最快写得最简单,完全可以新建字符串

时间复杂度\(O(n)\),空间复杂度$O(n) $

class Solution {
public:
    string replaceSpace(string s) {
        int len = s.length();
        if(len == 0) return s;
        string ans;
        for(int i = 0;i < len;++i){
            if(s[i]==' '){
                ans += "%20";
            }
            else ans += s[i];
        }
        return ans;
    }
};

如果要求空间最小,那么需要在原字符串上进行替换操作。

先求出空格个数,设定两个指针,一个指向要移动到的位置,一个指向原来的位置

ps:这题leetcode上差点意思,我就在牛客上提交的

时间复杂度\(O(n)\),没有新开空间

class Solution {
public:
    void replaceSpace(char *str,int length) {
        if(length == 0) return;
        int numberOfBlank = 0;
        for(int i = 0;i < length;++i){
            if(str[i] == ' ') numberOfBlank++;
        }
        int newStingLength = length + (numberOfBlank << 1);
        int p1 = newStingLength - 1,p2 = length - 1;
        
        while(p2 >= 0){
            if(str[p2] == ' '){
                str[p1--] = '0';
                str[p1--] = '2';
                str[p1--] = '%';
            }else{
                str[p1--] = str[p2];
            }
            p2--;
        }
    }
};

数据结构-链表

从头到尾打印链表

一开始我写成了不能开辟额外空间的链表反转

这种情况一定要问清楚,可不可以改变原链表的形状

时间复杂度\(O(n)\)

class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
         vector<int> ans;
        if(head == NULL) return ans;
        ListNode *preNode = NULL,*nowNode = head,*tmpNode = NULL;
        while(nowNode->next){
            tmpNode = nowNode->next;
            nowNode -> next = preNode;
            preNode = nowNode;
            nowNode = tmpNode;
        }
        nowNode -> next = preNode;
        while(nowNode){
            ans.push_back(nowNode->val);
            nowNode = nowNode -> next;
        }
        return ans;
    }
};

但是这种题已经要求了用数组存,那就可以用更简单更快的方法

class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
         vector<int> ans;
        if(head == NULL) return ans;
        ListNode *nowNode = head;
        int listLength = 0;
        while(nowNode){
            ans.push_back(nowNode->val);
            nowNode = nowNode ->next;
            listLength++;
        }
        for(int i = 0;i < listLength/2;++i){
            swap(ans[i],ans[listLength-i-1]);
        }
        return ans;
    }
};

翻转可以当作以中间的数作为根节点,然后左右子树交换。

除此之外还可采用栈的方法。

数据结构-树

标签:return,nums,int,复杂度,offer,ans,nowNode
来源: https://www.cnblogs.com/smallocean/p/12487468.html