此类问题,没有特定的模板,没有特定的算法,你需要做的是找规律,或者单纯的根据题意模拟一段过程
目录
67. 二进制求和
1487. 保证文件名唯一
31. 下一个排列
448. 找到所有数组中消失的数字
面试题67. 把字符串转换成整数
面试题31. 栈的压入、弹出序列
面试题17. 打印从1到最大的n位数
矩阵原地运算
48. 旋转图像
54. 螺旋矩阵
面试题45. 把数组排成最小的数
面试题43. 1~n整数中1出现的次数
面试题44. 数字序列中某一位的数字
面试题61. 扑克牌中的顺子
面试题62. 圆圈中最后剩下的数字
面试题58 - II. 左旋转字符串
面试题58 - I. 翻转单词顺序
面试题39. 数组中出现次数超过一半的数字
1488. 避免洪水泛滥
https://leetcode-cn.com/problems/avoid-flood-in-the-city/
218. 天际线问题
非常好的一道题目,逻辑参考:https://leetcode-cn.com/problems/the-skyline-problem/solution/218tian-ji-xian-wen-ti-sao-miao-xian-fa-by-ivan_al/
class Solution {
public:
vector> getSkyline(vector>& buildings) {
vector> h;
multiset m;//堆,自动排序
vector> res;
//1、将每一个建筑分成“两个部分”,例如:[2,9,10]可以转换成[2,-10][9,10],我们用负值来表示左边界,这也是很关键的一步,我们将前段点和后端点分开储存
for(const auto& b:buildings)
{
h.push_back({b[0], -b[2]});
h.push_back({b[1], b[2]});
}
//2、根据x值对分段进行排序
sort(h.begin(),h.end());
int prev = 0, cur = 0;
m.insert(0);
//3、遍历
for (auto i:h)
{
if (i.second < 0) m.insert(-i.second); //左端点,高度入堆
else m.erase(m.find(i.second)); //右端点,高度出堆
cur = *m.rbegin(); //当前最大高度高度
if (cur != prev) { //当前最大高度不等于最大高度perv表示这是一个转折点
res.push_back({i.first, cur}); //添加坐标
prev = cur; //更新最大高度
}
}
return res;
// https://leetcode-cn.com/problems/the-skyline-problem/solution/218tian-ji-xian-wen-ti-sao-miao-xian-fa-by-ivan_al/
}
};
https://leetcode-cn.com/problems/add-binary/
class Solution {
public:
string addBinary(string a, string b) {
//模拟过程题目
if(a.empty()&&b.empty()) return "";
if(a.empty()) return b;
if(b.empty()) return a;
int index1 = a.size() - 1;
int index2 = b.size() - 1;
int delta = 0;
stackRes;
while(index1>=0&&index2>=0)
{
// cout<=0)
{
if(a[index1] == '1')
{
if(delta == 1) {Res.push(0);delta = 1;}
else {Res.push(1);delta = 0;}
}
else
{
if(delta == 1) {Res.push(1);delta = 0;}
else {Res.push(0);delta = 0;}
}
index1--;
}
while(index2>=0)
{
if(b[index2] == '1')
{
if(delta == 1) {Res.push(0);delta = 1;}
else {Res.push(1);delta = 0;}
}
else
{
if(delta == 1) {Res.push(1);delta = 0;}
else {Res.push(0);delta = 0;}
}
index2--;
}
if(delta == 1) Res.push(1);
string Str = "";
while(Res.size())
{
// cout<
前置补零:
class Solution {
public:
string addBinary(string a, string b) {
//模拟过程题目
if(a.empty()&&b.empty()) return "";
if(a.empty()) return b;
if(b.empty()) return a;
//补0操作,短的部分前置补领
int i = a.size() - b.size();
if(i<0) i = -1*i;
if(a.size()>b.size()) while(i>0){b = "0"+b;i--;}
else if(a.size()0){a = "0"+a;i--;}
int index = a.size() - 1;
int delta = 0;
stackRes;
while(index>=0)
{
if(a[index] == '1'&&b[index] == '1')
{
if(delta == 1) {Res.push(1);delta = 1;}
else {Res.push(0);delta = 1;}
}
else if( (a[index] == '1'&&b[index] == '0')||(a[index] == '0'&&b[index] == '1') )
{
if(delta == 1) {Res.push(0);delta = 1;}
else {Res.push(1);delta = 0;}
}
else if(a[index] == '0'&&b[index] == '0')
{
if(delta == 1) {Res.push(1);delta = 0;}
else {Res.push(0);delta = 0;}
}
index--;
}
if(delta == 1) Res.push(1);
string Str = "";
while(Res.size()) {Str += to_string(Res.top());Res.pop();}
return Str;
}
};
https://leetcode-cn.com/problems/making-file-names-unique/
先审题,保存一个清晰的思路,再动手结题,利用Hash表,key为字符串,value保存再次出现同名文件名后,最小下标应该是多少。
class Solution {
public:
vector getFolderNames(vector& names) {
int size = names.size();
if(size == 0) return {};
vectorRes;
unordered_mapM;
for(int i = 0;i
找规律,如何找到第一个比原数组大的值
class Solution {
public:
void nextPermutation(vector& nums) {
if(nums.empty()) return;
int right = nums.size() - 1;
while(right>=1)
{
if(nums[right - 1] Temp(nums.rbegin(),nums.rend());
nums = Temp;
}
else
{
int Move = right-1;
int Change = nums[Move];//要交换的数值
//找到后半部分第一个大于Change的值,交换
while(right=nums[right]) break;
right++;
}
swap(nums[Move],nums[right - 1]);
//反转后半部分
int begin = Move+1,end = nums.size() - 1;
while(begin<=end)
{
swap(nums[begin],nums[end]);
end--;begin++;
}
}
return;
}
};
https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/
Hash表当然是无所畏惧了, 遍历一遍,把出现过的内容标记,然后遍历hash表,看看谁没有出现,直接记录
class Solution {
public:
vector findDisappearedNumbers(vector& nums) {
if(!nums.size()) return {};
vectorRes;
unordered_mapM;
int size = nums.size();
for(auto item:nums) M[item]++;
for(int i = 1;i<=size;++i) if(M[i] == 0) Res.push_back(i);
return Res;
}
};
原地操作:
class Solution {
public:
vector findDisappearedNumbers(vector& nums) {
if(nums.size()) return{};
vectorRes;
for(int i = 0;i=0&&newIndex0) nums[newIndex] *= -1;
}
for(int i = 0;i0) Res.push_back(i+1);
}
return Res;
}
};
https://leetcode-cn.com/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/
本题要注意很多的细节问题。
也有需要的特殊案例:
那么根据题意,我们从头开始,不断提出空格,知道遇到第一个不是空格的内容
然后从该内容开始,判断是否为正负号或者数字,如果都不是,那么直接返回0
如果是,那么保留正负号,继续往下遍历,一旦遇到非数字的内容,直接return掉即可
但是本题要考虑大数问题,所以我们在循环中增加判断,一旦越界直接break;
string和int相互转换常用接口:
string 变成 int :atoi()函数
int变成string:to_string()函数
判断是否为数字:isdigit(char);
本题核心代码:
for(int i = begin;i='0'&&str[i]<='9') Num = Num*10+str[i]-'0';
}
这是典型的字符串变数字的方法。
class Solution {
public:
int strToInt(string str) {
if(str.empty()) return 0;
//除去收尾多余内容
int begin = 0;
for(auto item:str)
{
if(item == ' ') begin++;
else break;
}
if(!(str[begin] == '+'||str[begin] == '-'||(str[begin]>='0'&&str[begin]<='9')))
return 0;
//内容转化开始
long sign = 1,Num = 0;//此处必须是long,而且不能是unsigned
if(str[begin] == '-') {begin++;sign = -1;}
else if(str[begin] == '+') {begin++;sign = 1;}
for(int i = begin;i='0'&&str[i]<='9') Num = Num*10+str[i]-'0';
else break;
if(Num>INT_MAX) return sign == 1?INT_MAX:INT_MIN;
}
return Num*sign;
}
};
https://leetcode-cn.com/problems/zhan-de-ya-ru-dan-chu-xu-lie-lcof/
class Solution {
public:
bool validateStackSequences(vector& pushed, vector& popped) {
stack Temp;//压入测试
int index = 0;
for(int i = 0;i
压入元素,对比栈顶和第一个出栈的元素是否相等(temp.top() == popped[point]),相等,出栈( temp.pop()),移动指针(++point)
如果不相等继续压入元素,并且每次压入一个都要比一次
https://leetcode-cn.com/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/
本题由于性质问题,不太可能出现在机考中,面试中倒是有可能
暴力解法:
class Solution {
public:
vector printNumbers(int n) {
vector Res;
if(n<=0) return Res;
int end = 1;
for(int j = 0;j
本题的核心就是考查大数问题,我们需要做的是在字符串上模拟数字加法
大数解法:
本题是用字符串实现加减法
class Solution {
public:
vector printNumbers(int n) {
int m = pow(10, n) - 1;
vector res(m);
for(int i = 0; i < m; i++){
res[i] = i + 1;
}
return res;
}
void printNumbers2(int n) {
string s = "0";
while(s.size() <= n){
cout << s << endl;
s = add(s);
}
}
string& add(string &s){
int i = s.size()-1;
while(i >= 0 && s[i] == '9'){
s[i--] = '0';
}
if(i < 0){
s = "1" + s;
}else{
s[i] = s[i] + 1;
}
return s;
}
};
// 作者:Echoooo
// 链接:https://leetcode-cn.com/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/solution/czi-fu-chuan-jia-fa-by-echoooo/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
参考解法:https://leetcode-cn.com/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/solution/c-3chong-jie-fa-by-xdb/
https://leetcode-cn.com/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/solution/czi-fu-chuan-jia-fa-by-echoooo/
面试题14- II. 剪绳子 II
https://leetcode-cn.com/problems/jian-sheng-zi-ii-lcof/
https://leetcode-cn.com/problems/rotate-image/
本题还是需要观察一下,才能入手的
不能整行的换,下面是本题代码思路的示意图:
两个两个换,才能整个完成选择
class Solution {
public:
void rotate(vector>& matrix) {
if(matrix.empty()) return;
int row = matrix.size(),col = matrix[0].size();
//从外到内进行替换
int BeginR = 0,EndR = row-1;
int BeginC = 0,EndC = col-1;
while(BeginRBeginR,jBeginR,j>BeginC;--i,--j)
{
swap(matrix[i][BeginC],matrix[EndR][j]);//第一行和第一列交换
}
//左列和底行
for(int i = EndR-1,j = BeginC+1;i>=BeginR,j<=EndC;--i,++j)
{
swap(matrix[EndR][j],matrix[i][EndC]);//第一行和第一列交换
}
//收缩
BeginR++;EndR--;BeginC++;EndC--;
cout<
https://leetcode-cn.com/problems/spiral-matrix/
面试题29. 顺时针打印矩阵 https://leetcode-cn.com/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/
本题没有任何花里胡哨的技巧等,就是单纯的模拟整个过程,思路要清晰
class Solution {
public:
vector spiralOrder(vector>& matrix) {
if(matrix.empty()) return{};
int m = matrix.size(),n = matrix[0].size();
int Rbegin = 0,Rend = m-1;
int Cbegin = 0,Cend = n-1;
vector Res;
while(Rbegin!=Rend||Cbegin!=Cend)
{
//第一行
for(int i = Cbegin;i <= Cend;++i)
if( (i>=0&&i=0&&i=0)&&matrix[i][Cend] != INT_MIN)//固定列
{Res.push_back(matrix[i][Cend]);matrix[i][Cend] = INT_MIN;}
if(Cbegin!=Cend) Cend--;
if(Rbegin!=Rend) Rbegin++;
//下侧
for(int i = Cend;i>=Cbegin;--i)
if((i>=0&&i=0)&&matrix[Rend][i] != INT_MIN)//固定行
{Res.push_back(matrix[Rend][i]);matrix[Rend][i] = INT_MIN;}
if(Rbegin!=Rend) Rend--;
//左侧
for(int i = Rend;i>=Rbegin;--i)
if((i>=0&&i
https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/
这是一道排序题
x+y>y+x,那么我们选择x+y这个组合就好了
class Solution {
public:
string minNumber(vector& nums) {
vector strs;
string res;
for(auto num:nums)
strs.push_back(to_string(num));
sort(strs.begin(),strs.end(),
[](const string &a,const string &b)
{return a+b
当然了,我们也是可以从大到小排列
class Solution {
public:
string minNumber(vector& nums) {
vector strs;
string res;
for(auto num:nums)
strs.push_back(to_string(num));
sort(strs.begin(),strs.end(),
[](const string &a,const string &b)
{return a+b>b+a;});
for(auto str:strs)
res+=str;
return res;
}
};
// 北冥有鱼
算法参考:https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/solution/mian-shi-ti-45-ba-shu-zu-pai-cheng-zui-xiao-de-s-4/
https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/
算法参考:https://leetcode-cn.com/problems/number-of-digit-one/solution/shu-zi-1-de-ge-shu-by-leetcode/
233. 数字 1 的个数 https://leetcode-cn.com/problems/number-of-digit-one/
这是一道单纯的找规律问题
class Solution {
public:
int countDigitOne(int n)
{
int countr = 0;
for (long long i = 1; i <= n; i *= 10) {
long long divider = i * 10;
countr += (n / divider) * i + min(max(n % divider - i + 1, 0LL), i);
}
return countr;
}
// 作者:LeetCode
// 链接:https://leetcode-cn.com/problems/number-of-digit-one/solution/shu-zi-1-de-ge-shu-by-leetcode/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
};
https://leetcode-cn.com/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/
400. 第N个数字 https://leetcode-cn.com/problems/nth-digit/
本题也是一道找规律的题目:
算法参考:https://leetcode-cn.com/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/solution/zhe-shi-yi-dao-shu-xue-ti-ge-zhao-gui-lu-by-z1m/
class Solution {
public:
int findNthDigit(int n) {
//(1)先看看是几位数(156是两位数)
long base = 9,Digits = 1;//Digits表示目前的数字在哪儿个区
while(n-base*Digits>0)
{
n -= base*Digits;
base *= 10;
Digits++;
}
//(2)找具体的值
long number = 1;//起步位置
for (int i = 1;i < Digits;i++)
number *= 10;
int dig = n % Digits;// Digits表示所在的区
if (dig == 0)dig = Digits;//如果能整除的话要减去1
// cout<
先看看目标值在哪儿个区间
long base = 9,Digits = 1;//Digits表示目前的数字在哪儿个区
while(n-base*Digits>0)
{
n -= base*Digits;
base *= 10;
Digits++;
}
9第一个区间长度
180第二个区间长度
270第三个区间长度
我们看看我们要找的位数是在哪儿个区间长度,比如156
现在在第二个区间,区间号码:Digits
从第二个区间的首部算起,找第156-9 = 147个数字
第一步完成
下面我们找第147位数字,原来的值是多少,显然是为
long number = 1;//起步位置
for (int i = 1;i < Digits;i++)
number *= 10;
以156为例,就是起步是10
10——99这180个中的第147个,因为Digits为2,所以直接147/Digits,数字都是两个两个一组,看看147在第几组
但是此处要考虑特殊情况比如找第11个数字,11-9 = 2,2/2 = 1;本来原数组是10,现在找到11了
所以先取余,看看到底是多少,不行就-1
int dig = n % Digits;// Digits表示所在的区
if (dig == 0)dig = Digits;//如果能整除的话要减去1
// cout<
现在我们也找到了要找的原始数据了
是83,那么147到底是那儿一位呢?
147对Digits取余,如果是0,那么就是最后一位,不然就是第一位
for (int i=dig;i
难度颇高
https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof/
本题比较单纯
class Solution {
public:
bool isStraight(vector& nums) {
sort(nums.begin(),nums.end());
int ZeroSize = 0;//大小王的个数
for(int i = 0;i1) ZeroSize = ZeroSize-Dleta+1;
if(Dleta == 0||ZeroSize < 0) return false;
}
return true;
}
};
https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/
https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/solution/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-by-lee/
https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/solution/javajie-jue-yue-se-fu-huan-wen-ti-gao-su-ni-wei-sh/
https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/
class Solution {
public:
string reverseLeftWords(string s, int n) {
if(s.empty()) return "";
int begin = 0;
n = n%s.size();
string Part1 = s.substr(0,n);
while(n)
{
n--;
begin++;
}
cout<
本题为字符串的拼接,找到旋转点,断开字符串,然后收尾拼接即可
合理运用栈的性质,先进后出,我们在提出了前后多余的空格后,将内容压入栈中,然后再一次输出,字符之间增加空格即可
class Solution {
public:
string reverseWords(string s) {
int size = s.size();
// cout<=0&&s[end] == ' ') end--;
// cout<end) return "";
stack Temp;
int point = begin;
while(point<=end)
{
string n = "";
while(point<=end&&s[point] != ' ') {n+=s[point];point++;}
if(n!="") Temp.push(n);
// cout<
https://leetcode-cn.com/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-lcof/
169. 多数元素 https://leetcode-cn.com/problems/majority-element/
机考直接Hash表秒杀,但是笔试的时候,怎么算才是最优?
class Solution {
public:
int majorityElement(vector& nums) {
if(!nums.size()) return 0;
unordered_map Map;
int MAX = 0,index = 0;
for(auto item:nums)
{
Map[item]++;
if( Map[item]>MAX )
{
MAX = Map[item];
index = item;
}
}
return index;
}
};
排序,超过一半,那么中位数一定是该数字
class Solution {
public:
int majorityElement(vector& nums) {
if(!nums.size()) return 0;
sort(nums.begin(),nums.end());
return nums[nums.size()/2];
}
};
使用莫尔投票法(Boyer-Moore):
算法参考:https://leetcode-cn.com/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-lcof/solution/mian-shi-ti-39-shu-zu-zhong-chu-xian-ci-shu-chao-3/
https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/
class Solution {
public:
int majorityElement(vector& nums) {
int candidate = -1;
int count = 0;
for (int num : nums) {
if (num == candidate)
++count;
else if (--count < 0) {
candidate = num;
count = 1;
}
}
return candidate;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/majority-element/solution/duo-shu-yuan-su-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
5437. 不同整数的最少数目
https://leetcode-cn.com/problems/least-number-of-unique-integers-after-k-removals/
合理运用hash表和vector数组
class Solution {
public:
int findLeastNumOfUniqueInts(vector& arr, int k) {
if(arr.empty()) return 0;
unordered_mapM;
for(auto item:arr) M[item]++;//记录出现次数
vectorTime;//创建一个保存出现次数的数组
for(auto item:M) Time.push_back(item.second);
int res = M.size();//多少个数字
sort(Time.begin(),Time.end());//对出现次数进行排序
for(auto item:Time)
{
//拿出相应的个数
if(item<=k) {k -= item;res--;}//本次拿走该数字后,k>=0,那么数字种类就要减1
else if(item>k) break;//本次拿走多少,都不会改变数字种类
}
return res;
}
};