Leetcode刷题第三期Week1——模拟

Posted RiddleLi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode刷题第三期Week1——模拟相关的知识,希望对你有一定的参考价值。

题目列表来自yxc大佬的AcWing Leetcode提高班第三期

Leetcode 263 Ugly Number

注意:特别地,1是Ugly Number

没什么要注意的,三个循环搞定

class Solution {
public:
    bool isUgly(int num) {
        if(num <= 0)
            return false;
        while(num % 2 == 0)
            num = num / 2;
        while(num % 3 == 0)
            num = num / 3;
        while(num % 5 == 0)
            num = num / 5;
        return num == 1;
    }
};

Leetcode 67 Add Binary

这题让我想起了高精度,权当是复习一下C++ 的字符串处理吧

class Solution {
public:
    string addBinary(string a, string b) {
        char c[100];
        memset(c, ‘‘, sizeof(c));
        if(a.size() < b.size()) swap(a, b);
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());
        int carry = 0;
        for(int i = 0; i < b.size(); i++) {
            int temp = carry + a[i] - ‘0‘ + b[i] - ‘0‘;
            if(temp >= 2) {
                temp -= 2;
                carry = 1;
            } else {
                carry = 0;
            }
            c[i] = temp + ‘0‘;
        }
        for(int i = b.size(); i < a.size(); i++) {
            int temp = carry + a[i] - ‘0‘;
            if(temp >= 2) {
                temp -= 2;
                carry = 1;
            } else {
                carry = 0;
            }
            c[i] = temp + ‘0‘;
        }
        if(carry == 1) c[a.size()] =‘1‘;    //注意:这里需要处理一下最高位的进位1(如果有的话)
        string result = c;
        reverse(result.begin(), result.end());
        return result;
    }
};

algorithm头文件中提供了swap reverse sort三个常用函数

memset是cstring头文件中提供的

yxc大佬给的wp的循环让人觉得非常精妙,这里也放一下,学习学习

总体思路是使用一个t不断地承接接下来要相加的两个数,然后每次除2即可,不用像我一样单独处理carrry和判断当前结果temp是否超过2了

string res;
int k = 0;
while (k < b.size())
{
  t += a[k] - ‘0‘ + b[k] - ‘0‘;
  res += to_string(t&1);
  t /= 2;
  k ++ ;
}

顺带一提,评论区有人用python写了个一行的,这里放一下,以示对python的尊敬

return bin(int(a,2)+int(b,2))[2:]

 Leetcode 504 Base 7

普普通通的进制转换,写就是了

class Solution {
public:
    string convertToBase7(int num) {
        if(num == 0) return "0";
        int num2 = num;
        if(num < 0) {
            num = -num;
        }
        string result;
        while(num != 0) {
            result += num % 7 + ‘0‘;
            num /= 7;
        }
        reverse(result.begin(), result.end());
        if(num2 < 0) result = "-" + result;
        return result;
    }
};

Leetcode 54 Spiral Matrix

这题是个最简单的推公式题,但是不知道为啥这题卡了这么久,简直有毒(菜没人权),matrix可能为空,可能为n*1的形式,这两个情况都导致我最开始的代码有问题:matrix为空在开头特判;matrix为3*3的时候,如果每个方向上的终止条件都是<,不是<=,最中间的5将没有人能够够到;最终变成了如下的代码:前三个方向都是<=,每个方向结束后立即比对一次count是否超过了总数,一旦超过了,立刻停止循环,感觉写的逻辑有点乱

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int> >& matrix) {
        vector<int> result;
        int m = matrix.size();
        if(m == 0) {
            return result;
        }
        int n = matrix[0].size();
        int count = 0;                  //计数器
        int number = 0;                 //第几圈
        while(count <= m*n) {
            for(int i = number; i <= n - 1 - number; i++) {
                //left to right
                result.push_back(matrix[number][i]);
                count++;
            }
            if(count >= m * n) break;
            for(int i = number + 1; i <= m - 1 - number; i++) {
                //up to down
                result.push_back(matrix[i][n-1-number]);
                count++;
            }
            if(count >= m * n) break;
            for(int i = n-number-2; i >= number; i--) {
                //right to left
                result.push_back(matrix[m-1-number][i]);
                count++;
            }
            if(count >= m * n) break;
            for(int i = m-number-2; i > number; i--) {
                //down to up
                result.push_back(matrix[i][number]);
                count++;
            }
            if(count >= m * n) break;
            number++;
        }
        return result;
    }
};

评论区很多人采取了四对0 +1 -1组合的方式来转换坐标,只要当前的组合(比如说0, +1)还能继续往前,那就继续,否则就换到下一个组合

这种方案的代码示例如下(来自yxc大佬)

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if (matrix.empty()) return vector<int>();
        int n = matrix.size(), m = matrix[0].size();
        vector<vector<bool>> st(n, vector<bool>(m, false));
        int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
        int x = 0, y = 0, d = 0;
        vector<int> res;
        for (int i = 0; i < n * m; i ++ )
        {
            int a = x + dx[d], b = y + dy[d];
            if (a < 0 || a >= n || b < 0 || b >= m || st[a][b])
            {
                d = (d + 1) % 4;
                a = x + dx[d], b = y + dy[d];
            }
            res.push_back(matrix[x][y]);
            st[x][y] = true;
            x = a, y = b;
        }
        return res;
    }
};

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/13479/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Leetcode 24 Swap Nodes in Pairs

链表题,草稿打清楚,写过去就好了(注意要把p1->next修改成p2->next才能使链接上)

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

Leetcode 299 Bulls and Cows

这个题WA了一次,原因是我最开始在拼字符串的时候是把整型转成了一个char进行拼接的,当计数超过10的时候就会出现错误,于是更改成为了to_string()函数,这个函数来自string头文件

题的思路没什么,就记得cow要把bull减下去就好了,就一个比较和一个木桶

class Solution {
public:
    string getHint(string secret, string guess) {
        //we assume that secret.length == guess.length
        int bull = 0, cow = 0;
        int numbers[2][10] = {0};                  //Wooden barrel
        //0代表secret, 1代表guess
        for(int i = 0; i < secret.size(); i++) {
            bull = bull + (secret[i]==guess[i]);
            numbers[0][secret[i]-‘0‘]++;
            numbers[1][guess[i]-‘0‘]++;
        }
        for(int i = 0; i < 10; i++) {
            cow = cow + min(numbers[0][i], numbers[1][i]);
        }
        string result;
        result = result + to_string(bull) + "A";
        result = result + to_string(cow - bull) + "B";
        return result;
    }
};

 Leetcode 481 Magical String

略乱,需要打草稿理清楚变量之间的关系,理清楚就a了

class Solution {
public:
    int magicalString(int n) {
        int count = 3;
        vector<int> a;
        a.push_back(1);
        a.push_back(2);
        a.push_back(2);
        if(n <= 0)
            return 0;
        if(n >= 1 && n <= 3)
            return 1;
        int index = 2;
        int result = 1;
        while(count < n) {
            for(int i = 0; i < a[index]; i++) a.push_back(2-(index+1)%2);
            if(index % 2 == 0) result += a[index];
            count = count + a[index];
            index++;
            
        }
        if(count > n && index % 2 == 1) {
            result--;
        }
        return result;
    }
};

 Leetcode 71 Simplify Path

用一个栈来维护字符串的信息(头文件<stack>),C++没有字符串split,需要自己实现…………

class Solution {
public:
    string simplifyPath(string path) {
        string temp;
        //将原字符串按/进行分割(相当于实现了一个split函数)
        stack<string> b;
        for(int i = 0; i < path.size(); i++) {
            if(path[i] == ‘/‘) {
                if(temp != "") {
                    if(temp == "..") {
                        if(!b.empty())
                            b.pop();
                    }
                    else if(temp != "."){
                        b.push(temp);
                    }
                }
                temp = "";
            } else {
                temp = temp + path[i];
            }
        }
        if(temp != "" && temp != "/") {
            if(temp == "..") {
                if(!b.empty())
                    b.pop();
            }
            else if(temp != "."){
                b.push(temp);
            }
        }
        string result;
        while(!b.empty()) {
            result = "/" + b.top() + result;
            b.pop();
        }
        if(result == "")
            result = "/";
        return result;
    }
};

 评论区老哥的一句话js……服气服气

var simplifyPath = (path, currPath = []) => {return path.split(‘/‘).forEach(item => (item === ‘..‘)? currPath.pop() : ((item && item !== ‘.‘)? currPath.push(item):‘‘)), ‘/‘ + currPath.join(‘/‘)}

 Leetcode 12 Integer to Roman

分情况讨论

class Solution {
public:
    string intToRoman(int num) {
        int a[4];
        int i = 0;
        while(num != 0) {           //从个位到千位
            a[i++] = num % 10;
            num /= 10;
        }
        //i是位数
        char tran[4][2] = {‘I‘, ‘V‘, ‘X‘, ‘L‘, ‘C‘, ‘D‘, ‘M‘, ‘‘};
        string result;
        for(int j = 0; j < i; j++) {
            if(a[j] == 0) {
                continue;
            }
            else if(a[j] == 9) {
                result = result + tran[j+1][0] + tran[j][0];
            }
            else if(a[j] == 4) {
                result = result + tran[j][1] + tran[j][0];
            }
            else if(a[j] >= 5) {
                for(int k = 0; k < a[j] - 5; k++) {
                    result = result + tran[j][0];
                }
                result = result + tran[j][1];
            } else {
                for(int k = 0; k < a[j]; k++) {
                    result = result + tran[j][0];
                }
            }
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

yxc大佬给的思路更为清晰,外层for和内层的while配合的很完美,只要你还足够大就一直减这一级,精妙精妙,这里也贴一下

class Solution {
public:
    string intToRoman(int num) {
        int values[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
        string reps[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

        string res;
        for (int i = 0; i < 13; i ++ )
            while(num >= values[i])
            {
                num -= values[i];
                res += reps[i];
            }
        return res;
    }
};

作者:yxc
链接:https://www.acwing.com/solution/LeetCode/content/101/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 Leetcode 68 Text Justification

先将数据分割成若干行长度小于等于MaxWidth的行(统计长度应该注意把词与词之间的间隔中的空格统计进去)

如果是最后一行,则只实现左对齐:每个单词之间插入一个空格,行尾插入若干空格,使这一行的总长度是 maxWidth
如果这一行只有一个单词,则直接在行尾补上空格
其他情况,则需计算总共要填补多少空格,然后按题意均分在单词之间(左多右少)

class Solution {
public:
    vector<string> fullJustify(vector<string>& words, int maxWidth) {
        vector<string> result;
        vector<vector<string> > Array;
        vector<string> temp;
        int length = 0;
        for(int i = 0; i < words.size(); i++) {
            if(length == 0) {
                //行首不应该有空格
                length += words[i].size();
                temp.push_back(words[i]);
            }
            else if(length + 1 + words[i].size() <= maxWidth) {
                //词与词之间应该有空格
                length = length + 1 + words[i].size();
                temp.push_back(words[i]);
            }
            else {
                //放不开当前这一个了,应该结算
                Array.push_back(temp);
                length = words[i].size();
                temp.clear();
                temp.push_back(words[i]);
            }
        }
        //结束之后如果temp数组不为空,进行一次额外结算,这一定是最后一行,所以可以特殊处理
        if(temp.size() > 0) {
            Array.push_back(temp);
        }
        //开始拼接字符串,注意:最后一行需要特殊处理,因此单独列出
        for(int i = 0; i < Array.size() - 1; i++) {
            length = 0;
            for(int j = 0; j < Array[i].size(); j++) {
                length += Array[i][j].size();
            }
            int delta = maxWidth - length;
            int num = Array[i].size() - 1;          //缝隙数目
            string t;
            if(num == 0) {
                //如果没有缝隙(这一行就这一个单词,我们需要把这个字符串后面全部填上空格)
                t = Array[i][0];
                for(int j = 0; j < delta; j++) t += " ";
                result.push_back(t);
            } else {
                //缝隙数目大于等于1,均匀分配,左多右少
                for(int j = 0; j < num; j++) {
                    t = t + Array[i][j];
                    for(int k = 0; k < delta / num; k++) t += " ";  //均匀分配的部分
                    if(j < delta % num) t += " ";                   //左多右少的额外空格
                }
                t += Array[i][Array[i].size() - 1];
                result.push_back(t);
            }
        }
        //开始处理最后一行
        string t;
        length = 0;
        int lastLine = Array.size()-1;
        for(int i = 0; i < Array[lastLine].size()-1; i++) {
            t = t + Array[lastLine][i] + " ";
            length = length + Array[lastLine][i].size() + 1;
        }
        t = t + Array[lastLine][Array[lastLine].size()-1];
        length = length + Array[lastLine][Array[lastLine].size()-1].size();
        int delta = maxWidth - length;
        for(int i = 0; i < delta; i++) {
            t = t + " ";
        }
        result.push_back(t);
        return result;
    }
};

 Happy Birthday!    hhh

以上是关于Leetcode刷题第三期Week1——模拟的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode刷题第一周

Leetcode刷题第003天

LeetCode算法题--刷题第一天

LeetCode开心刷题第四天——7逆序8字符转数字

蓝桥杯备赛刷题

蓝桥杯备赛刷题