目录

​416. 分割等和子集​

​421. 数组中两个数的最大异或值​

​429. N叉树的层序遍历​

​431. 将 N 叉树编码为二叉树​

​438. 找到字符串中所有字母异位词​

​451. 根据字符出现频率排序​

​454. 四数相加 II​

​461. 汉明距离​

​470. 用 Rand7() 实现 Rand10()​

​478. 在圆内随机生成点​

​486. 预测赢家​

​496. 下一个更大元素 I​

​503. 下一个更大元素 II​

​509. 斐波那契数​

​510. 二叉搜索树中的中序后继 II​

​515. 在每个树行中找最大值​

​523. 连续的子数组和​

​525. 连续数组​

​528. 按权重随机选择​

​535. TinyURL 的加密与解密​

​540. 有序数组中的单一元素​

​542. 01 矩阵​

​556. 下一个更大元素 III (整数和字符串互相化)​

​559. N 叉树的最大深度​

​560. 和为K的子数组​

​567. 字符串的排列​

​589. N 叉树的前序遍历​

​590. N 叉树的后序遍历​

​621. 任务调度器​

​630. 课程表 III​

646.%20%E6%9C%80%E9%95%BF%E6%95%B0%E5%AF%B9%E9%93%BE">​646. 最长数对链​

​673. 最长递增子序列的个数​

​680. 验证回文字符串 Ⅱ​

​693. 交替位二进制数​

​698. 划分为k个相等的子集​

​713. 乘积小于K的子数组​

​720. 词典中最长的单词​

​724. 寻找数组的中心下标​

​738. 单调递增的数字​

​740. 删除与获得点数​

​762. 二进制表示中质数个计算置位​

​767. 重构字符串​


416. 分割等和子集

​javascript:void(0)​

421. 数组中两个数的最大异或值

基数树 ​​基数树(radix tree)_nameofcsdn的博客-CSDN博客_基数树​

429. N叉树的层序遍历

多叉树 ​​多叉树_nameofcsdn的博客-CSDN博客​

431. 将 N 叉树编码为二叉树

树 ​​树、森林_nameofcsdn的博客-CSDN博客​

438. 找到字符串中所有字母异位词

剑指 Offer II 015. 字符串中的所有变位词

​javascript:void(0)​

451. 根据字符出现频率排序

题目:

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

示例 1:

输入:

"tree"

输出:

"eert"

解释:

'e'出现两次,'r'和't'都只出现一次。

因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。

示例 2:

输入:

"cccaaa"

输出:

"cccaaa"

解释:

'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。

注意"cacaca"是不正确的,因为相同的字母必须放在一起。

示例 3:

输入:

"Aabb"

输出:

"bbAa"

解释:

此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。

注意'A'和'a'被认为是两种不同的字符。

代码:

struct dist
{
char c;
int fre;
};
struct cmp
{
bool operator()(dist a, dist b)
{
return a.fre < b.fre;
}
};

class Solution {
public:
string frequencySort(string s) {
map<char, int> m;
priority_queue<dist, vector<dist>, cmp>que;
dist d;
for (int i = 0; i < s.length();i++)
{
m[s[i]]++;
}
for (auto it = m.begin(); it != m.end(); it++)
{
d.c = (*it).first, d.fre = (*it).second, que.push(d);
}
string ans = "";
while (!que.empty())
{
d = que.top();
que.pop();
while(d.fre--)ans += d.c;
}
return ans;
}
};

454. 四数相加 II

数组和集合的搜索 ​​数组和集合的搜索_nameofcsdn的博客-CSDN博客​

461. 汉明距离

题目:

两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。

给出两个整数 x 和 y,计算它们之间的汉明距离。

注意:

0 ≤ x, y < 231.

示例:

输入: x = 1, y = 4

输出: 2

解释:

1   (0 0 0 1)

4   (0 1 0 0)

       ↑   ↑

上面的箭头指出了对应二进制位不同的位置。

代码:

class Solution {
public:
int hammingWeight(uint32_t n) {
int ans = 0;
while (n)
{
n ^= (n&(-n));
ans++;
}
return ans;
}
int hammingDistance(int x, int y) {
return hammingWeight(x^y);
}
};

470. 用 Rand7() 实现 Rand10()

拒绝采样 ​​拒绝采样(Rejection Sampling)_nameofcsdn的博客-CSDN博客​

478. 在圆内随机生成点

拒绝采样​

486. 预测赢家

给定一个表示分数的非负整数数组。 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,……。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。

给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。

示例 1:

输入: [1, 5, 2]

输出: False

解释: 一开始,玩家1可以从1和2中进行选择。

如果他选择2(或者1),那么玩家2可以从1(或者2)和5中进行选择。如果玩家2选择了5,那么玩家1则只剩下1(或者2)可选。

所以,玩家1的最终分数为 1 + 2 = 3,而玩家2为 5。

因此,玩家1永远不会成为赢家,返回 False。

示例 2:

输入: [1, 5, 233, 7]

输出: True

解释: 玩家1一开始选择1。然后玩家2必须从5和7中进行选择。无论玩家2选择了哪个,玩家1都可以选择233。

最终,玩家1(234分)比玩家2(12分)获得更多的分数,所以返回 True,表示玩家1可以成为赢家。

注意:

1 <= 给定的数组长度 <= 20.

数组里所有分数都为非负数且不会大于10000000。

如果最终两个玩家的分数相等,那么玩家1仍为赢家。

区间DP:

int res[20][20],flag[20][20];

int PredictTheWinner2(int* nums, int numsSize,int low,int high){
if(low>high)return 0;
if(flag[low][high])return res[low][high];
flag[low][high]=1;
return res[low][high]=max(nums[low]-PredictTheWinner2(nums,numsSize,low+1,high),nums[high]-PredictTheWinner2(nums,numsSize,low,high-1));
}
bool PredictTheWinner(int* nums, int numsSize){
memset(flag,0,sizeof(res));
return PredictTheWinner2(nums,numsSize,0,numsSize-1)>=0;
}

496. 下一个更大元素 I

给定两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。

nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

示例 1:

输入: nums1 = [4,1,2], nums2 = [1,3,4,2].

输出: [-1,3,-1]

解释:

    对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。

    对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。

    对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。

示例 2:

输入: nums1 = [2,4], nums2 = [1,2,3,4].

输出: [3,-1]

解释:

    对于 num1 中的数字 2 ,第二个数组中的下一个较大数字是 3 。

    对于 num1 中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出 -1 。


提示:

nums1和nums2中所有元素是唯一的。

nums1和nums2 的数组大小都不超过1000。

这个题目很简单,我主要用来锻造我的模板:

//翻转vector
template<typename T>
vector<T> frev(vector<T> v)
{
vector<T> ans;
for(int i=v.size()-1;i>=0;i--)ans.push_back(v[i]);
return ans;
}
//vector乘一个数
template<typename T1,typename T2>
void fcheng(vector<T1> &v,T2 n)
{
for(int i=v.size()-1;i>=0;i--)v[i]*=n;
}
//vector加一个数
template<typename T1,typename T2>
void fjia(vector<T1> &v,T2 n)
{
for(int i=v.size()-1;i>=0;i--)v[i]+=n;
}
//id处,覆盖或者添加x
template<typename T>
void finsert(vector<T>&v,int id,T x)
{
if(id<0||id>v.size())return;
if(id==v.size())v.push_back(x);
v[id]=x;
}

//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
template<typename T,class P>inline
vector<int>firstInLeft(vector<T>v,P pr)
{
vector<int> ans;
if(v.size()==0)return ans;
stack<T>st;
st.push(0);
ans.push_back(-1);
for(int i=1;i<v.size();i++)
{
while(!st.empty() && !pr(v[st.top()],v[i]))st.pop();
if(st.empty())ans.push_back(-1);
else ans.push_back(st.top());
st.push(i);
}
return ans;
}

//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
template<typename T>
vector<int> fminlef(vector<T> v)
{
return firstInLeft(v,[](T a,T b){return a<b;});
}
//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
template<typename T>
vector<int> fminlef2(vector<T> v)
{
return firstInLeft(v,[](T a,T b){return a<=b;});
}
//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
template<typename T>
vector<int> fmaxlef(vector<T> v)
{
fcheng(v,-1);
vector<int>ans=fminlef(v);
return ans;
}
//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
template<typename T>
vector<int> fmaxlef2(vector<T> v)
{
fcheng(v,-1);
vector<int>ans=fminlef2(v);
return ans;
}


//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
template<typename T>
vector<int> fminrig(vector<T> v)
{
vector<int>v1=frev(v),v2=fminlef(v1);
fcheng(v2,-1);
fjia(v2,v.size()-1);
return frev(v2);
}
//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
template<typename T>
vector<int> fminrig2(vector<T> v)
{
vector<int>v1=frev(v),v2=fminlef2(v1);
fcheng(v2,-1);
fjia(v2,v.size()-1);
return frev(v2);
}
//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
template<typename T>
vector<int> fmaxrig(vector<T> v)
{
vector<int>v1=frev(v),v2=fmaxlef(v1);
fcheng(v2,-1);
fjia(v2,v.size()-1);
return frev(v2);
}
//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
template<typename T>
vector<int> fmaxrig2(vector<T> v)
{
vector<int>v1=frev(v),v2=fmaxlef2(v1);
fcheng(v2,-1);
fjia(v2,v.size()-1);
return frev(v2);
}

//把id转化为对应的数
template<typename T>
vector<int> fgetNumFromId(vector<T> &v,vector<int>id)
{
vector<T>ans;
ans.resize(id.size());
for(int i=0;i<id.size();i++)ans[i]= (id[i]>=0 && id[i]<v.size()) ? v[id[i]] : -1;
return ans;
}
//把v1和v2 转化成1个map<v1,v2>
template<typename T1,typename T2>
map<T1,T2> vectorToMap(vector<T1> &v1,vector<T2> &v2)
{
map<T1,T2>m;
for(int i=0;i<v1.size();i++)m[v1[i]]=v2[i];
return m;
}
//1个vector加1个map转化成map[vector]
template<typename T1,typename T2>
vector<T2> vmToVector(vector<T1> &v,map<T1,T2>&m)
{
vector<T2>ans;
ans.resize(v.size());
for(int i=0;i<v.size();i++)ans[i]=m[v[i]];
return ans;
}

class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
vector<int>ans=fgetNumFromId(nums2,fmaxrig(nums2));
map<int,int>m=vectorToMap(nums2,ans);
ans=vmToVector(nums1,m);
return ans;
}
};

503. 下一个更大元素 II

给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

示例 1:

输入: [1,2,1]

输出: [2,-1,2]

解释: 第一个 1 的下一个更大的数是 2;

数字 2 找不到下一个更大的数; 

第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

//翻转vector
template<typename T>
vector<T> frev(vector<T> v)
{
vector<T> ans;
for(int i=v.size()-1;i>=0;i--)ans.push_back(v[i]);
return ans;
}
//vector乘一个数
template<typename T1,typename T2>
void fcheng(vector<T1> &v,T2 n)
{
for(int i=v.size()-1;i>=0;i--)v[i]*=n;
}
//vector加一个数
template<typename T1,typename T2>
void fjia(vector<T1> &v,T2 n)
{
for(int i=v.size()-1;i>=0;i--)v[i]+=n;
}
//id处,覆盖或者添加x
template<typename T>
void finsert(vector<T>&v,int id,T x)
{
if(id<0||id>v.size())return;
if(id==v.size())v.push_back(x);
v[id]=x;
}

//返回vector每个数前面最近的满足pr关系的数的ID,-1 或者 0到size-1
template<typename T,class P>inline
vector<int>firstInLeft(vector<T>v,P pr)
{
vector<int> ans;
if(v.size()==0)return ans;
stack<T>st;
st.push(0);
ans.push_back(-1);
for(int i=1;i<v.size();i++)
{
while(!st.empty() && !pr(v[st.top()],v[i]))st.pop();
if(st.empty())ans.push_back(-1);
else ans.push_back(st.top());
st.push(i);
}
return ans;
}

//返回vector每个数前面最近的比它小的数的ID,-1 或者 0到size-1
template<typename T>
vector<int> fminlef(vector<T> v)
{
return firstInLeft(v,[](T a,T b){return a<b;});
}
//返回vector每个数前面最近的比它小或等于的数的ID,-1 或者 0到size-1
template<typename T>
vector<int> fminlef2(vector<T> v)
{
return firstInLeft(v,[](T a,T b){return a<=b;});
}
//返回vector每个数前面最近的比它大的数的ID,-1 或者 0到size-1
template<typename T>
vector<int> fmaxlef(vector<T> v)
{
fcheng(v,-1);
vector<int>ans=fminlef(v);
return ans;
}
//返回vector每个数前面最近的比它大或等于的数的ID,-1 或者 0到size-1
template<typename T>
vector<int> fmaxlef2(vector<T> v)
{
fcheng(v,-1);
vector<int>ans=fminlef2(v);
return ans;
}


//返回vector每个数后面最近的比它小的数的ID,size 或者 0到size-1
template<typename T>
vector<int> fminrig(vector<T> v)
{
vector<int>v1=frev(v),v2=fminlef(v1);
fcheng(v2,-1);
fjia(v2,v.size()-1);
return frev(v2);
}
//返回vector每个数后面最近的比它小或等于的数的ID,size 或者 0到size-1
template<typename T>
vector<int> fminrig2(vector<T> v)
{
vector<int>v1=frev(v),v2=fminlef2(v1);
fcheng(v2,-1);
fjia(v2,v.size()-1);
return frev(v2);
}
//返回vector每个数后面最近的比它大的数的ID,size 或者 0到size-1
template<typename T>
vector<int> fmaxrig(vector<T> v)
{
vector<int>v1=frev(v),v2=fmaxlef(v1);
fcheng(v2,-1);
fjia(v2,v.size()-1);
return frev(v2);
}
//返回vector每个数后面最近的比它大或等于的数的ID,size 或者 0到size-1
template<typename T>
vector<int> fmaxrig2(vector<T> v)
{
vector<int>v1=frev(v),v2=fmaxlef2(v1);
fcheng(v2,-1);
fjia(v2,v.size()-1);
return frev(v2);
}

//把v和id转化为v[id]
template<typename T>
vector<int> fgetNumFromId(vector<T> &v,vector<int>id)
{
vector<T>ans;
ans.resize(id.size());
for(int i=0;i<id.size();i++)ans[i]= (id[i]>=0 && id[i]<v.size()) ? v[id[i]] : -1;
return ans;
}
//把v1和v2 转化成1个map<v1,v2>
template<typename T1,typename T2>
map<T1,T2> vectorToMap(vector<T1> &v1,vector<T2> &v2)
{
map<T1,T2>m;
for(int i=0;i<v1.size();i++)m[v1[i]]=v2[i];
return m;
}
//1个vector加1个map转化成map[vector]
template<typename T1,typename T2>
vector<T2> vmToVector(vector<T1> &v,map<T1,T2>&m)
{
vector<T2>ans;
ans.resize(v.size());
for(int i=0;i<v.size();i++)ans[i]=m[v[i]];
return ans;
}

class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
vector<int>t=nums;
t.resize(nums.size()*2);
copy(nums.begin(),nums.end(),t.begin()+nums.size());
vector<int>tmp=fgetNumFromId(t,fmaxrig(t));
vector<int>ans=nums;
copy(tmp.begin(),tmp.begin()+tmp.size()/2,ans.begin());
return ans;
}
};

509. 斐波那契数

斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1

F(n) = F(n - 1) + F(n - 2),其中 n > 1

给你 n ,请计算 F(n) 。

示例 1:

输入:2

输出:1

解释:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

输入:3

输出:2

解释:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

输入:4

输出:3

解释:F(4) = F(3) + F(2) = 2 + 1 = 3


提示:

0 <= n <= 30

class Solution {
public:
int fib(int n) {
static int ans[101]={0,1};
if(n<2)return ans[n];
if(ans[n])return ans[n];
return ans[n]=(fib(n-1)+fib(n-2))%1000000007;
}
};

510. 二叉搜索树中的中序后继 II

二叉搜索树​

515. 在每个树行中找最大值

剑指 Offer II 044. 二叉树每层的最大值 ​​javascript:void(0)​

523. 连续的子数组和

给定一个包含非负数的数组和一个目标整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数。

示例 1:

输入: [23,2,4,6,7], k = 6

输出: True

解释: [2,4] 是一个大小为 2 的子数组,并且和为 6。

示例 2:

输入: [23,2,6,4,7], k = 6

输出: True

解释: [23,2,6,4,7]是大小为 5 的子数组,并且和为 42。

说明:

数组的长度不会超过10,000。

你可以认为所有数字总和在 32 位有符号整数范围内。

class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
if(k==0)
{
for(int i=1;i<nums.size();i++)
{
if(nums[i]==0&&nums[i-1]==0)return true;
}
return false;
}
map<int,int>m;
int s=0;
if(k<0)k=-k;
for(int i=0;i<nums.size();i++)
{
s+=nums[i];
s%=k;
if(m[s]>0||s==0)
{
if(m[s]<i)return true;
}
else m[s]=i+1;
}
return false;
}
};

525. 连续数组

剑指 Offer II 010. 和为 k 的子数组 ​​javascript:void(0)​

528. 按权重随机选择

剑指 Offer II 071. 按权重生成随机数 ​​javascript:void(0)​

535. TinyURL 的加密与解密

加解密​

540. 有序数组中的单一元素

二分、三分 ​

542. 01 矩阵

给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。

两个相邻元素间的距离为 1 。

示例 1:

输入:

[[0,0,0],

 [0,1,0],

 [0,0,0]]

输出:

[[0,0,0],

 [0,1,0],

 [0,0,0]]

示例 2:

输入:

[[0,0,0],

 [0,1,0],

 [1,1,1]]

输出:

[[0,0,0],

 [0,1,0],

 [1,2,1]]


提示:

给定矩阵的元素个数不超过 10000。

给定矩阵中至少有一个元素是 0。

矩阵中的元素只在四个方向上相邻: 上、下、左、右。

#define NUM(x,y) ((x<0||x>=A.size()||y<0||y>=A[0].size())? -1:A[x][y])
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};

class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& A) {
vector<vector<int>>ans=A;
for(int i=0;i<ans.size();i++)for(int j=0;j<ans[0].size();j++)ans[i][j]=-1;
queue<int>q;
for(int i=0;i<A.size();i++)for(int j=0;j<A[0].size();j++)if(A[i][j]==0)
{
ans[i][j]=0;
q.push(i*10000+j);
}
while(!q.empty())
{
int k=q.front();
q.pop();
int kx=k/10000,ky=k%10000;
for(int dire=0;dire<4;dire++)
{
int kxx=kx+dx[dire],kyy=ky+dy[dire];
if(NUM(kxx,kyy)==-1)continue;
if(ans[kxx][kyy]!=-1)continue;
q.push(kxx*10000+kyy);
ans[kxx][kyy]=ans[kx][ky]+1;
}
}
return ans;
}
};

556. 下一个更大元素 III (整数和字符串互相转化)

给定一个32位正整数 n,你需要找到最小的32位整数,其与 n 中存在的位数完全相同,并且其值大于n。如果不存在这样的32位整数,则返回-1。

示例 1:

输入: 12

输出: 21

示例 2:

输入: 21

输出: -1

char* itoa(int num,char* str,int radix)  //copy from 百度百科
{/*索引表*/
char index[]="0123456789ABCDEF";
unsigned unum;/*中间变量*/
int i=0,j,k;
/*确定unum的值*/
if(radix==10&&num<0)/*十进制负数*/
{
unum=(unsigned)-num;
str[i++]='-';
}
else unum=(unsigned)num;/*其他情况*/
/*转换*/
do{
str[i++]=index[unum%(unsigned)radix];
unum/=radix;
}while(unum);
str[i]='\0';
/*逆序*/
if(str[0]=='-')
k=1;/*十进制负数*/
else
k=0;

for(j=k;j<=(i-1)/2;j++)
{ char temp;
temp=str[j];
str[j]=str[i-1+k-j];
str[i-1+k-j]=temp;
}
return str;
}
class Solution {
public:
int nextGreaterElement(int n) {
char sn[40];
itoa(n,sn,10);
int len=strlen(sn);
for(int i=len-2;i>=0;i--)
{
if(sn[i]>=sn[i+1])continue;
for(int j=len-1;j>i;j--)
{
if(sn[i]>=sn[j])continue;
sn[j]^=sn[i]^=sn[j]^=sn[i];
sort(sn+i+1,sn+len);
long long res = atol(sn);
if(res==int(res))return res;
return -1;
}
}
return -1;
}
};

后来发现可以用c++的库函数获取上一个下一个全排列,就更简单了。

class Solution {
public:
int nextGreaterElement(int n) {
char sn[40];
itoa(n,sn,10);
int len=strlen(sn);
if(!next_permutation(sn,sn+len))return -1;
long long res = atol(sn);
if(res==int(res))return res;
return -1;
}
};

559. N 叉树的最大深度

多叉树 ​

560. 和为K的子数组

剑指 Offer II 010. 和为 k 的子数组 ​​javascript:void(0)​

567. 字符串的排列

剑指 Offer II 014. 字符串中的变位词 ​​javascript:void(0)​

589. N 叉树的前序遍历

多叉树​

590. N 叉树的后序遍历

多叉树​

621. 任务调度器

贪心 ​

630. 课程表 III

贪心​

646. 最长数对链

DP ​

673. 最长递增子序列的个数

DP ​​

680. 验证回文字符串 Ⅱ

剑指 Offer II 019. 最多删除一个字符得到回文

​javascript:void(0)​

693. 交替位二进制数

题目:

给定一个正整数,检查他是否为交替位二进制数:换句话说,就是他的二进制数相邻的两个位数永不相等。

示例 1:

输入: 5

输出: True

解释:

5的二进制数是: 101

示例 2:

输入: 7

输出: False

解释:

7的二进制数是: 111

示例 3:

输入: 11

输出: False

解释:

11的二进制数是: 1011

 示例 4:

输入: 10

输出: True

解释:

10的二进制数是: 1010

代码:

class Solution {
public:
bool hasAlternatingBits2(int n) {
if (n == 0)return true;
if (n % 4 == 1)return hasAlternatingBits2(n / 4);
return false;
}
bool hasAlternatingBits(int n) {
if (n % 2 == 0)n /= 2;
return hasAlternatingBits2(n);
}
};

698. 划分为k个相等的子集

题目:

给定一个整数数组  nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。

示例 1:

输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4

输出: True

说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。


注意:

1 <= k <= len(nums) <= 16

0 < nums[i] < 10000

思路:

DFS,注意剪枝,我这里采用的是简单的降序排序,排序可以让执行时间从2000ms降为4ms

代码:

int s[16];

class Solution {
public:
bool canPartitionKSubsets(vector<int> &nums, int k, int deep)
{
if (deep >= nums.size())return true;
for (int j = 0; j <= deep && j < k; j++) {
if (s[j] < nums[deep])continue;
s[j] -= nums[deep];
if (canPartitionKSubsets(nums, k, deep + 1))return true;
s[j] += nums[deep];
}
return false;
}
bool canPartitionKSubsets(vector<int> &nums, int k)
{
if (nums.size() < k || k <= 0 || k > 16)return false;
sort(nums.begin(),nums.end(),greater<int>());
int anss = 0;
for (auto it = nums.begin(); it != nums.end(); it++) anss += *it;
if (anss % k) return false;
anss /= k;
for (int i = 0; i < k; i++) s[i] = anss;
return canPartitionKSubsets(nums, k, 0);
}
};

713. 乘积小于K的子数组

剑指 Offer II 009. 乘积小于 K 的子数组 ​​javascript:void(0)​

720. 词典中最长的单词

给出一个字符串数组words组成的一本英语词典。从中找出最长的一个单词,该单词是由words词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。

若无答案,则返回空字符串。

示例 1:

输入:

words = ["w","wo","wor","worl", "world"]

输出:"world"

解释: 

单词"world"可由"w", "wo", "wor", 和 "worl"添加一个字母组成。

示例 2:

输入:

words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]

输出:"apple"

解释:

"apply"和"apple"都能由词典中的单词组成。但是"apple"的字典序小于"apply"。


提示:

所有输入的字符串都只包含小写字母。

words数组长度范围为[1,1000]。

words[i]的长度范围为[1,30]。

2021年2月25日做了这题,这也是我把力扣题解汇总到几篇博客之后,第一次插入新题解。

我的代码:(动态规划的备忘录写法)

map<string,int>exitt;
map<string,int>m;

void init(vector<string>& words)
{
exitt.clear();
m.clear();
for(int i=0;i<words.size();i++){
exitt[words[i]]=1;
}
}

string preString(string s)
{
if(s.length()<=1){
return "";
}
return s.substr(0,s.length()-1);
}

int dp(string s)
{
if(m[s])return m[s];
if(s.length()==1)return 1;
if(exitt[preString(s)] && dp(preString(s))>0)return m[s]=dp(preString(s))+1;
return m[s]=-1;
}

class Solution {
public:
string longestWord(vector<string>& words) {
init(words);
string ans="";
for(int i=0;i<words.size();i++){
int ret=dp(words[i]);
if(ret==-1)continue;
if(ans.length()<words[i].length() || ans.length()==words[i].length() && ans>words[i])
ans=words[i];
}
cout<<exitt["e"];
return ans;
}
};

也可以用字典树做。

724. 寻找数组的中心下标

剑指 Offer II 012. 左右两边子数组的和相等 ​​javascript:void(0)​

738. 单调递增的数字

题目:

给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。

(当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。)

示例 1:

输入: N = 10

输出: 9

示例 2:

输入: N = 1234

输出: 1234

示例 3:

输入: N = 332

输出: 299

说明: N 是在 [0, 10^9] 范围内的一个整数。

代码:

class Solution {
public:
int monotoneIncreasingDigits(int N) {
int key = 1111111111, ans = 0, num = 9;
while (key)
{
while (N >= key && num > 0)
{
N -= key, ans += key, num--;
}
key /= 10;
}
return ans;
}
};

740. 删除与获得点数

给定一个整数数组 nums ,你可以对它进行一些操作。

每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除每个等于 nums[i] - 1 或 nums[i] + 1 的元素。

开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

示例 1:

输入: nums = [3, 4, 2]

输出: 6

解释: 

删除 4 来获得 4 个点数,因此 3 也被删除。

之后,删除 2 来获得 2 个点数。总共获得 6 个点数。

示例 2:

输入: nums = [2, 2, 3, 3, 3, 4]

输出: 9

解释: 

删除 3 来获得 3 个点数,接着要删除两个 2 和 4 。

之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。

总共获得 9 个点数。

注意:

nums的长度最大为20000。

每个整数nums[i]的大小都在[1, 10000]范围内。

class Solution {
public:
int s[10001];
int ans[10001];
int dp(int k)
{
if(k<0)return 0;
if(ans[k])return ans[k];
return ans[k]=max(s[k]+dp(k-2),dp(k-1));
}
int deleteAndEarn(vector<int>& nums) {
if(nums.size()==0)return 0;
memset(ans,0,sizeof(int)*10001);
memset(s,0,sizeof(int)*10001);
for(int i=0;i<nums.size();i++)s[nums[i]]+=nums[i];
return dp(10000);
}
};

762. 二进制表示中质数个计算置位

题目:

给定两个整数 L 和 R ,找到闭区间 [L, R] 范围内,计算置位位数为质数的整数个数。

(注意,计算置位代表二进制表示中1的个数。例如 21 的二进制表示 10101 有 3 个计算置位。还有,1 不是质数。)

示例 1:

输入: L = 6, R = 10

输出: 4

解释:

6 -> 110 (2 个计算置位,2 是质数)

7 -> 111 (3 个计算置位,3 是质数)

9 -> 1001 (2 个计算置位,2 是质数)

10-> 1010 (2 个计算置位,2 是质数)

示例 2:

输入: L = 10, R = 15

输出: 5

解释:

10 -> 1010 (2 个计算置位, 2 是质数)

11 -> 1011 (3 个计算置位, 3 是质数)

12 -> 1100 (2 个计算置位, 2 是质数)

13 -> 1101 (3 个计算置位, 3 是质数)

14 -> 1110 (3 个计算置位, 3 是质数)

15 -> 1111 (4 个计算置位, 4 不是质数)

注意:

L, R 是 L <= R 且在 [1, 10^6] 中的整数。

R - L 的最大值为 10000。

代码:

class Solution {
public:
int hammingWeight(int n) {
int ans = 0;
while (n)
{
n ^= (n&(-n));
ans++;
}
return ans;
}
int countPrimeSetBits(int L, int R) {
set<int>se = { 2, 3, 5, 7 ,11,13,17,19};
int ans = 0;
for (int i = L; i <= R; i++)
{
if (se.find(hammingWeight(i)) != se.end())ans++;
}
return ans;
}
};

767. 重构字符串

贪心