2021-12-25每日刷题打卡
力扣——剑指offer
剑指 Offer 29. 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
我们从x=0,y=0处开始逐步把数存入数组里,准备四个方向:上(-1,0),右(0,1),下(1,0),左(0,-1),每次遍历的时候按照方向xy坐标的不同加在我们遍历的xy处就可以达到顺时针遍历,每当遇到边界或是到了之前的位置(转了一圈)就转方向。
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int n=matrix.size();
vector<int>v;
if(!n)return v;
int m=matrix[0].size();
vector<vector<bool>>st(n,vector<bool>(m,false));
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int x=0,y=0,d=1;
for(int i=0;i<n*m;i++)
{
v.push_back(matrix[x][y]);
st[x][y]=true;
int a=x+dx[d],b=y+dy[d];
if(a>=n||a<0||b<0||b>=m||st[a][b])
{
d=(d+1)%4;
a=x+dx[d],b=y+dy[d];
}
x=a,y=b;
}
return v;
}
};
剑指 Offer 64. 求1+2+…+n
求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
示例 1:
输入: n = 3
输出: 6
不能使用循环我们还能用递归,但因为不能使用if,使得我们利用递归也有点麻烦,这里利用的是逻辑运算符&&的特性:当左边为假时,不会运行右边的程序,我们就可以以n放在&&的左边,右边是递归相加的程序,当n为0时就不会运行右边的程序了,从而使递归停止。
class Solution {
public:
int sum=0;
int sumNums(int n) {
n&&(sum+=n)&&sumNums(--n);
return sum;
}
};
剑指 Offer 31. 栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
示例 1:
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
模拟栈的入栈出栈,先入栈,当入栈元素和出栈队列的元素相同时,不对这个元素进行入栈操作,同时选择下一位出栈序列的元素,;如果当前入栈元素和出栈元素不同就把这个元素入栈。入栈操作结束后再进行出栈操作,每次判断栈顶元素是否和遍历到的出栈元素相同,相同就把这个元素出栈,同时选择下一位出栈序列的元素,如果不相同,就返回false。如果出栈完了也没返回false,就返回true。
class Solution {
public:
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
int n=pushed.size(),m=popped.size(),j=0;
stack<int>sta;
for(int i=0;i<n;i++)
{
if(pushed[i]==popped[j])
{
j++;
while(!sta.empty()&&sta.top()==popped[j])
{
sta.pop();
j++;
}
}
else
{
sta.push(pushed[i]);
}
}
while(!sta.empty())
{
if(sta.top()==popped[j])
{
sta.pop();
j++;
}
else
{
return false;
}
}
return true;
}
};
剑指 Offer 56 - I. 数组中数字出现的次数
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
先对nums排序,然后从第二个元素开始遍历nums,每次拿当前元素和它的上一个元素作比较,如果不相同,就把上一个元素插入vector数组v中,如果相同,那就把当前元素向后挪两次(防止下一个元素和当前元素比较时不相同插入v),遍历完后如果v的元素只有一个,说明nums数组的最后一个元素也是只出现一个的元素,把它也插入v中,最后返回v。
class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<int>v;
int n=nums.size();
for(int i=1;i<n;i++)
{
if(nums[i]!=nums[i-1])
v.push_back(nums[i-1]);
else i++;
}
if(v.size()==1)v.push_back(nums[n-1]);
return v;
}
};
剑指 Offer 56 - II. 数组中数字出现的次数 II
在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。
示例 1:
输入:nums = [3,4,3,3]
输出:4
准备一个map容器,遍历nums数组,每次遍历到一个数,就把它在map中出现的次数++,结束后遍历map,找到出现次数为1的那个数。
class Solution {
public:
int singleNumber(vector<int>& nums) {
unordered_map<int,int>mymap;
for(auto i:nums)
mymap[i]++;
for(auto i:mymap)
if(i.second==1)
return i.first;
return 0;
}
};