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——模拟的主要内容,如果未能解决你的问题,请参考以下文章