美文网首页
Weekly Contest 64题解

Weekly Contest 64题解

作者: leetcode周赛题解 | 来源:发表于2017-12-25 16:25 被阅读0次

    Largest Number Greater Than Twice of Others

    题意

    判断一个数组最大的元素是否是其他元素的至少2倍

    思路

    循环判断一下就好了

    代码

    class Solution {
    public:
        int dominantIndex(vector<int>& nums) {
            if (nums.empty()) {
                return -1;
            }
            
            int n = nums.size();
            int max_idx = max_element(nums.begin(), nums.end()) - nums.begin();
            for (int i = 0; i < n; ++i) {
                if (i == max_idx) {
                    continue;
                }
                if (nums[i] && nums[max_idx] / nums[i] < 2) {
                    return -1;
                }
            }
            return max_idx;
        }
    };
    

    IP to CIDR

    题意

    题意比较迷醉。给出一个ip和数字n,求出最少的CIDR正好覆盖n个IP

    CIDR就是类似于这种表示方式:255.0.0.8/29,显然一个CIDR可以覆盖多少IP,比如255.0.0.8/29可以覆盖8个IP

    并且题目没有说的是,求出来的CIDR必须是从给定的ip开始连续的,例如题目的样例如果输出["255.0.0.8/29","255.0.0.14/31"]则不行,因为要从255.0.0.7开始连续,而如果这样输出就没有255.0.0.7这个ip

    思路

    容易想到,一个CIDR(xxx.xxx.xxx.xxx/y)能够覆盖的ip是2的32-y次幂个ip,例如y为29时可以覆盖8个ip,那么要让CIDR最少,就贪心的每次都让y尽可能大就行了,然后再注意一下必须是连续的

    代码

    class Solution {
    public:
        vector<string> ipToCIDR(string ip, int range) {
            vector<string> ret;
            uint32_t num = ip2num(ip);
            while (range) {
                int weight = 1;
                int i = 0;
                while (i < 32) {
                    weight <<= 1;
                    if ((1 << i & num) || (weight > range)) {
                        break;
                    }
                    ++i;
                }
                weight >>= 1;
                range -= weight;
                ret.emplace_back(num2ip(num) + "/" + to_string(32 - i));
                num += weight;
            }
            return ret;
        }
    private:
        int ip2num(const string& ip) {
            vector<string> vec = split(ip, '.');
            int num = 0;
            num = static_cast<int>(stoi(vec[0]));
            num = num << 8 | static_cast<int>(stoi(vec[1]));
            num = num << 8 | static_cast<int>(stoi(vec[2]));
            num = num << 8 | static_cast<int>(stoi(vec[3]));
            return num;
        }
        string num2ip(int num) {
            vector<string> vec;
            for (int i = 0; i < 4; ++i) {
                vec.emplace_back(to_string(num & 0xff));
                num = num >> 8;
            }
            string ret;
            ret.append(vec[3] + '.');
            ret.append(vec[2] + '.');
            ret.append(vec[1] + '.');
            ret.append(vec[0]);
            return ret;
        }
        vector<string> split(const string& str, char delim) {
            stringstream ss(str);
            string word;
            vector<string> ret;
            while (getline(ss, word, delim)) {
                ret.emplace_back(word);
            }
            return ret;
        }
    };
    

    Open the Lock

    题意

    一把锁由4位数字组成,每次可以把每一位+1或者-1,特殊的,9+1会变为0,1-1会变回9,锁的初始状态是0000,并且不能变为deadends里的数字,求最少多少步变到target

    思路

    从0000开始bfs就好了,再判断一下是不是deadend

    代码

    class Solution {
    public:
        int openLock(vector<string>& deadends, string target) {
            fill(begin(deadend), end(deadend), false);
            fill(begin(min_step), end(min_step), -1);
    
            int target_num = stoi(target);
            for (const auto& str : deadends) {
                deadend[stoi(str)] = true;
            }
            
            if (deadend[0]) {
                return -1;
            }
    
            queue<int> que;
            que.push(0);
            min_step[0] = 0;
            while (!que.empty()) {
                int head = que.front();
                if (head == target_num) {
                    return min_step[head];
                }
                que.pop();
                for (int i = 0; i < 4; ++i) {
                    int next = head;
                    int digit = at(head, i);
                    int new_digit = (digit + 1) % 10;
                    next = head - digit * power(10, i) + new_digit * power(10, i);
                    if (check(next)) {
                        min_step[next] = min_step[head] + 1;
                        que.push(next);
                    }
    
                    new_digit = (digit + 9) % 10;
                    next = head - digit * power(10, i) + new_digit * power(10, i);
                    if (check(next)) {
                        min_step[next] = min_step[head] + 1;
                        que.push(next);
                    }
                }
            }
            return -1;
        }
    private:
        int at(int num, int pos) {
            return num / power(10, pos) % 10;
        }
        int power(int x, int y) {
            int ret = 1;
            while (y--) {
                ret = ret * x;
            }
            return ret;
        }
        bool check(int num) {
            return num >= 0 && num < 10000 && !deadend[num] && min_step[num] == -1;
        }
        bool deadend[10000];
        int min_step[10000];
    };
    

    Cracking the Safe

    题意

    将k进制下的n位数排列并且连接起来,并且前一个数字的后半部分和后一个数字的前半部分的公共部分可以抵消,例如123和234连接后就会变成1234(23是公共部分),求出总长度最小的排列连接方式

    思路

    参考【deBruijn序列】,dfs暴力的去填当前这个数字是多少,贪心的让当前这个数字的前n-1位和前一个数字的后n-1位相同,也就是暴力枚举当前这个数字的最后一位是几

    代码

    class Solution {
    public:
        string crackSafe(int n, int k) {
            string ret;
            assert(dfs(0, n, k, 0, power(k, n), &ret));
            reverse(ret.begin(), ret.end());
            return ret;
        }
    private:
        bool dfs(int depth, int n, int k, int pre, int left, string *ans) {
            if (depth < n) {
                for (int i = 0; i < k; ++i) {
                    if (dfs(depth + 1, n, k, pre * 10 + i, left, ans)) {
                        ans->push_back(static_cast<char>('0' + i));
                        return true;
                    }
                }
            } else {
                order[depth - n] = pre;
                visit[pre] = true;
                if (left == 1) {
                    return true;
                }
                for (int i = 0; i < k; ++i) {
                    int cur = pre % power(k, n - 1) * k + i;
                    if (visit[cur]) {
                        continue;
                    }
                    if (dfs(depth + 1, n, k, cur, left - 1, ans)) {
                        ans->push_back(static_cast<char>('0' + i));
                        return true;
                    }
                }
                visit[pre] = false;
            }
            return false;
        }
        int power(int a, int b) {
            int ret = 1;
            while (b--) {
                ret = ret * a;
            }
            return ret;
        }
        bool visit[10000];
        int order[10000];
    };
    

    leetcode周赛题解每周更新,请关注微信公众号 [leetcode周赛题解] 或者
    [lc_tijie]

    [图片上传失败...(image-ca9d1f-1514190321906)]

    相关文章

      网友评论

          本文标题:Weekly Contest 64题解

          本文链接:https://www.haomeiwen.com/subject/szwlgxtx.html