Leetcode第130场周赛总结

130

第一次参加周赛,感觉有点小紧张,leetcode题库里面的题会给出它的标签,比较容易根据题目标签想到思路。而周赛就不会给你这些提示了,所以写的很惨QAQ。因为自己习惯于提示了,遇见裸题目就会不知所措,要改一下这个毛病啊~

1028. 负二进制转换

给出数字 N,返回由若干 "0""1"组成的字符串,该字符串为 N负二进制(base -2)表示。

除非字符串就是 "0",否则返回的字符串中不能含有前导零。

示例 1:

输入:2
输出:"110"
解释:(-2) ^ 2 + (-2) ^ 1 = 2

可以观察到:偶数位是正数,奇数位是负数

对于二进制的每一位,如果它是1,说明这一位有权重,0则表示没有,而且位数越高,权重越大。

我们从右往左看(因为除2取余法是从后往前得到结果的)。例如 110第0位是0, 第一位是1而且是奇数位,即(-2) ^ 1,第二位是 1 而且是偶数位,即(-2) ^ 2。 所以不用考虑位是0的情况,就算是奇数位也没有任何影响。

2的正常二进制表示是10 , 可是这里的 “1”在奇数位,具有负数权重,表示 -2 ,想办法将它改成正数权重就能正确的表示 2 了。在二进制中,\(2 ^ n - 2 ^{ (n-1)} = 2 ^ {(n-1)}\)。所以往高位加1,第二位变为 1 * (2^2) = 4,4 - |-2| = 2,相当于我们用高位抵消掉了低位的负权重并且加上了正确的正权重。(在程序中,因为当前位是1,所以当前数字加 1 就相当于往高位进1 )

其他数位正常使用除2取余法。

class Solution {
public:
    string baseNeg2(int N) {
        //偶数位是正的
        if(N==0) return "0";
        string res;
        while(N)
        {
            int t = N%2;
            if(t) N--; //如果这一位有权重,就加1,这里N在奇数位是负数,所以减1
            N/=-2;
            if(!t) res += '0';
            else res+='1';
        }
        
        reverse(res.begin(),res.end());
        
        return res;
    }
};

## 1019. 链表中的下一个更大节点

给出一个以头节点 head 作为第一个节点的链表。链表中的节点分别编号为:node_1, node_2, node_3, ...

每个节点都可能有下一个更大值(next larger value):对于 node_i,如果其 next_larger(node_i)node_j.val,那么就有 j > inode_j.val > node_i.val,而 j 是可能的选项中最小的那个。如果不存在这样的 j,那么下一个更大值为 0

返回整数答案数组 answer,其中 answer[i] = next_larger(node_{i+1})

注意:在下面的示例中,诸如 [2,1,5] 这样的输入(不是输出)是链表的序列化表示,其头节点的值为 2,第二个节点值为 1,第三个节点值为 5 。

示例 1:

输入:[2,1,5]
输出:[5,5,0]

思路:把当前位置 i 入栈,往后遍历,发现第一个比栈顶元素大的数字就 pop() ,并记下当前节点的 next larger value。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> nextLargerNodes(ListNode* head) {
        vector<int> nums;
        while(head)
        {
            nums.push_back(head->val);
            head=  head->next;
        }
        
        int n = nums.size();
        vector<int> res(n,0);
        stack<int> s;
        for(int i=0;i<n;i++)
        {
            while(!s.empty()&& nums[i]>nums[s.top()])
            {
                auto temp = s.top();
                s.pop();
                res[temp] = nums[i];
            }
            s.push(i);
        }
        return res;
    }
};

## 1020. 飞地的数量

给出一个二维数组 A,每个单元格为 0(代表海)或 1(代表陆地)。

移动是指在陆地上从一个地方走到另一个地方(朝四个方向之一)或离开网格的边界。

返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。

示例 1:

输入:[[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
输出:3
解释: 
有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。

思路:似曾相识的感觉,好像做过类似的题~ 题目的意思是要求出孤立在海中的陆地。从网格边缘开始,如果是陆地(1),就把与它相连的陆地(1)全部变为海水(0),海水中孤立的陆地不会与这些从边缘开始延伸的陆地相连,所以最后。。。真的就被孤立了
class Solution {
public:
    int count = 0;
    
    int dx[4] = {0,1,0,-1}, dy[4] = {1,0,-1,0};
    int numEnclaves(vector<vector<int>>& A) {
        int m = A.size(),n = A[0].size();
        for(int i=0;i<m;i++)
        {
            if(A[i][0] == 1) dfs(A,i,0);
            if(A[i][n-1] == 1) dfs(A,i,n-1);
        }
        for(int j=0;j<n;j++)
        {
            if(A[0][j] == 1) dfs(A,0,j);
            if(A[m-1][j] == 1) dfs(A,m-1,j);
        }
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
            {
                if(A[i][j] == 1) count++;
            }
        return count;
    }
    
    void dfs(vector<vector<int>> &A,int x,int y)
    {
        A[x][y] = 0;
         int m = A.size(),n = A[0].size();
        for(int i=0;i<4;i++)
        {
            int xx = x+dx[i];
            int yy = y+dy[i];
            if(xx>=0&&xx<m && yy>=0&&yy<n &&  A[xx][yy] == 1)
            {
                dfs(A,xx,yy);
            }
        }
    }
};

第一次参赛,深刻意识到了自己和大佬的差距,别人20分钟四道题就写完了orz 。对自己没什么好说的,还是练习的太少了,总结好每一次吧~

posted @ 2019-04-01 19:55  Leo_26  阅读(248)  评论(0编辑  收藏  举报