剑指Offer_WEEK02

剑指 Offer 13. 机器人的运动范围

算法(bfs) o(nm)

思路:

这是一个典型的宽度优先搜索问题,我们从 (0, 0) 点开始,每次朝上下左右四个方向扩展新的节点即可。

扩展时需要注意新的节点需要满足如下条件:

  • 之前没有遍历过,这个可以用个bool数组来判断
  • 没有走出边界
  • 横纵坐标的各位数字之和小于 k

最后答案就是所有遍历过的合法的节点个数

每个节点最多只会入队一次,所以时间复杂度不会超过方格中的节点个数

最坏情况下会遍历方格中的所有点,所以时间复杂度就是 o(nm)。

class Solution {
public:

    int get_single_num(int x){
        int s = 0;
        while(x) s += x % 10,x /= 10;
        return s;
    }
    
    int get_sum(pair<int,int> p){
        return get_single_num(p.first) + get_single_num(p.second);
    }

    int movingCount(int rows, int cols,int threshold)
    {
        int res = 0;
        if(!rows || !cols)
            return 0;
        vector<vector<bool>> st(rows,vector<bool>(cols));
        queue<pair<int,int>> q;
        q.push({0,0});
        int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};
        while(q.size()){
            auto t = q.front();
            q.pop();
            if(get_sum(t) > threshold || st[t.first][t.second])
                continue;
            res++;
            st[t.first][t.second] = true;
            for(int i = 0;i < 4;i++){
                int x = t.first + dx[i],y = t.second + dy[i];
                if(x >= 0 && x < rows && y >= 0 && y < cols){
                    q.push({x,y});
                }
            }
        }
        return res;
    }
};

剑指 Offer 14- I. 剪绳子

待补充

剑指 Offer 14- II. 剪绳子 II

待补充

剑指 Offer 15. 二进制中1的个数

算法:位运算 o(logn)

迭代进行如下两步,直到 n变成0为止:

  1. 如果n在二进制表示下末尾是1,则在答案中加1
  2. 将n右移一位,也就是将n在二进制表示下的最后一位删掉

这里有个难点是如何处理负数。
在C++中如果我们右移一个负整数,系统会自动在最高位补1,这样会导致 n永远不为0,就死循环了。
解决办法是把 n强制转化成无符号整型,这样 n 的二进制表示不会发生改变,但在右移时系统会自动在最高位补0。

时间复杂度

每次会将n除以2,最多会除 logn 次,所以时间复杂度是O(logn)。

class Solution {
public:
    int lowbit(uint32_t x){
        return x & -x;
    }
    int hammingWeight(uint32_t n) {
        int cnt = 0;
        while(n){
            cnt++;
            n -= lowbit(n);
        }
        return cnt;    
    }
};

 剑指 Offer 16. 数值的整数次方

算法:模拟 o(n)

由于本题的指数是int范围,可能很大,所以需要用快速幂求解

注意当指数是负数时,我们需要先取指数的绝对值,最后将乘积的倒数作为答案

时间复杂度

假设指数是 n,则一共会循环 O(logn)次,所以时间复杂度是O(logn)。

class Solution {
public:
    double myPow(double x, int n) {
        typedef long long LL;
        bool is_minus = n < 0;
        double res = 1;
        for (LL k = abs(LL(n)); k; k >>= 1) {
            if (k & 1) res *= x;
            x *= x;
        }
        if (is_minus) res = 1 / res;
        return res;
    }
};

剑指 Offer 18. 删除链表的节点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        if(!head)
            return NULL;
        if(head->val == val)
            return head->next;
        head->next = deleteNode(head->next,val);
        return head;
    }
};

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

class Solution {
public:
    vector<int> exchange(vector<int>& array) {
        vector<int> odd,even;
        for(int i = 0;i < array.size();i++){
            if(array[i] % 2 == 1)
                odd.push_back(array[i]);
            else
                even.push_back(array[i]);
        }
        int k = 0;
        for(int i = 0;i < odd.size();i++){
            array[k++] = odd[i];
        }
        for(int i = 0;i < even.size();i++){
            array[k++] = even[i];
        }
        return array;
    }
};

剑指 Offer 22. 链表中倒数第k个节点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* getKthFromEnd(ListNode* head, int k) {
        ListNode* tail = head;
        for(int i = 0;i < k - 1;i++){
            tail = tail->next;
        }
        while(tail->next){
            tail = tail->next;
            head = head->next;
        }
        return head;
    }
};

  

posted @ 2020-12-03 11:38  五岁就很帅🎈  阅读(77)  评论(0)    收藏  举报