1619. 删除某些元素后的数组均值 - 简单ac
class Solution {
public:
double trimMean(vector& arr) {
sort(arr.begin(),arr.end());
int idx=arr.size()*0.05;
double sum=0;
for(int i=idx;i
672. 灯泡开关 Ⅱ - 中等 - 思维
class Solution {
public:
int flipLights(int n, int presses) {
if(presses==0) return 1;
else if(n==1) return 2;
else if(n==2) return presses==1?3:4;
else
return presses==1?4:presses==2?7:8;
}
};
850. 矩形面积 II - 困难
typedef long long LL;
typedef pairPII;
const int mod=1e9+7;
class Solution {
public:
LL calc(vector>&rts,int a,int b)
{
vectorq;
for(auto x:rts)
{
if(x[0]<=a&&x[2]>=b)
q.push_back({x[1],x[3]});
}
sort(q.begin(),q.end());
LL res=0,st=-1e8,ed=-1e8;
for(auto x:q)
{
if(x.first>ed)
{
if(ed!=-1e8)res+=ed-st;
st=x.first,ed=x.second;
}
else if(x.second>ed)ed=x.second;
}
res+=ed-st;
return res*(b-a);
}
int rectangleArea(vector>& rts) {
vectorxs;
for(auto x:rts)xs.push_back(x[0]),xs.push_back(x[2]);
sort(xs.begin(),xs.end());
LL res=0;
for(int i=1;i
1624. 两个相同字符之间的最长子字符串 - 简单ac
class Solution {
public:
int maxLengthBetweenEqualCharacters(string s) {
unordered_mapmp;
int res=-1,t;
for(int i=0;i
1636. 按照频率将数组升序排序 - 简单ac
class Solution {
public:
vector frequencySort(vector& nums) {
unordered_mapmp;
for(int x:nums) mp[x]++;
sort(nums.begin(),nums.end(),[&](int a, int b)
{
if(mp[a]!=mp[b]) return mp[a]b;
});
return nums;
}
};
698. 划分为k个相等的子集 - 中等 dfs
class Solution {
public:
bool canPartitionKSubsets(vector& nums, int k) {
int n=nums.size();
int sum=0;
for(auto x:nums) sum+=x;
if(sum%k) return false;
int ave=sum/k;
sort(nums.begin(),nums.end());
if(aveb;
for(int i=0;i&nums,int cur,int k,vector&b)
{
if(cur<0) return true; //如果数组全部遍历完 说明所有数都放进桶了
for(int i=0;i0&&b[i]==b[i-1]) continue; //如果该情况和上一个是相同的 则不用向下遍历
if(b[i]==nums[cur]||b[i]-nums[cur]>=nums[0])//刚好能放桶里 或 一个桶能放多个
{
b[i]-=nums[cur];
if(dfs(nums,cur-1,k,b)) return true;
b[i]+=nums[cur];
}
}
return false;
}
};
1640. 能否连接形成数组 - 简单 - 哈希表
哈希表
class Solution {
public:
bool canFormArray(vector& arr, vector>& pieces) {
unordered_map m;
for(int i=0;i
1652. 拆炸弹 - 简单 - 前缀和
前缀和
循环数组求和可以把该数组弄成两份 预处理前缀和
比如:5 7 1 4 5 7 1 4
注意sum[0]=0
若k>0 则范围为【i+1, i+k+1】
如 5 7 1 4 5 7 1 4 i=0,k=3时,res = sum[i+k+1] - sum[i+1]
若k<0 则范围为【i+n+k, i+n】
如 5 7 1 4 5 7 1 4 i=0,k=-2时,res = sum[i+n] - sum[i+n+k]
class Solution {
public:
vector decrypt(vector& code, int k) {
int n=code.size();
vectorres(n,0);
vectorsum(2*n+10,0);
if(k==0) return res;
for(int i=1;i<=n*2;i++) sum[i]=sum[i-1]+code[(i-1)%n];
for(int i=0;i
拼接数组解决循环数组
class Solution {
public:
vector decrypt(vector& code, int k) {
int n=code.size();
vectorres,v;
for(int i=0;i<3;i++)
for(auto x:code) v.push_back(x);
for(int i=n;i<2*n;i++)
{
int sum=0;
if(k>0) for(int j=i+1;j
788. 旋转数字 - 中等 - 模拟
枚举1~n每一个数 先用数组记录每个数字反转情况
比如2反转后为5 7反转后不是数字 则记录-1
用y记录反转后的数 如果中间出现反转后非数字的数 直接return false
最后x和y比较 如果x!=y 说明是有效数 cnt++
class Solution {
public:
int rotatedDigits(int n) {
int cnt=0;
for(int i=1;i<=n;i++) cnt+=check(i);
return cnt;
}
bool check(int x)
{
vector d={0,1,5,-1,-1,2,9,-1,8,6};
int t=x,y=0,k=1;
while(t)
{
int p=t%10;
if(d[p]==-1) return false;
y+=k*d[p];
t/=10;
k*=10;
}
return x!=y;
}
};
面试题 17.09. 第 k 个数 - 中等 - dp 三指针 / 小顶堆
方法一:三指针 dp
class Solution {
public:
int getKthMagicNumber(int k) {
vectordp(k+1);
dp[1]=1;
int p1=1,p2=1,p3=1;
for(int i=2;i<=k;i++)
{
dp[i]=min({dp[p1]*3,dp[p2]*5,dp[p3]*7});
if(dp[i]==dp[p1]*3) p1++;
if(dp[i]==dp[p2]*5) p2++;
if(dp[i]==dp[p3]*7) p3++;
}
return dp[k];
}
};
方法二:小顶堆
用哈希表去重
class Solution {
public:
int getKthMagicNumber(int k)
{
int res;
int help[3]={3,5,7};
if(k==1)return 1;
priority_queue,greater>que;
set st;//排重
que.push(3);
que.push(5);
que.push(7);
int index=1;
while(indexINT_MAX)continue;//超出范围,禁止入内
if(st.count(a*tmp))continue;//出现过,跳过
else st.insert(a*tmp);
que.push(a*tmp);
}
}
return res;
}
};
同类型拓展—— 264. 丑数 II
面试题 01.08. 零矩阵 - 中等 - vector存pair
class Solution {
public:
void setZeroes(vector>& a) {
int m=a.size(),n=a[0].size();
vector> v;
for(int i=0;i
1694. 重新格式化电话号码 - 简单ac
class Solution {
public:
string reformatNumber(string number) {
vectorv;
int cnt=0,k;
string res;
if(number.size()<4) return number;
for(auto x:number) if(x>='0'&&x<='9') v.push_back(x);
int t=v.size();
for(int i=0;i
777. 在LR字符串中交换相邻字符 - 中等 - 双指针
class Solution {
public:
bool canTransform(string start, string end) {
int n=start.size();
int i=0,j=0;
while(ij)||(start[i]=='L'&&i
1784. 检查二进制字符串字段 - 简单 - 思维
class Solution {
public:
bool checkOnesSegment(string s) {
return s.find("01")==s.npos; //s.npos表示不存在的位置
}
};
921. 使括号有效的最少添加 - 中等ac
class Solution {
public:
int minAddToMakeValid(string s) {
stackst;
int cnt=0;
for(int i=0;i
811. 子域名访问计数 - 中等 - 模拟+string 操作
class Solution {
public:
vector subdomainVisits(vector& cp) {
unordered_mapmp;
for(auto s:cp)
{
int pos=s.find(' ');
int cnt=stoi(s.substr(0,pos)); //记录次数 stoi()把n进制字符串转化为十进制
while(pos!=-1)
{
mp[s.substr(pos+1)]+=cnt;
pos=s.find('.',pos+1); //pos更新为下一个点的下标 s.find(a,b)-从b的位置开始找a
}
}
vectorres;
for(auto &[s,cnt]:mp)
res.push_back(to_string(cnt)+' '+s); //to_string()将数字转化为字符
return res;
}
};
927. 三等分 - 困难 - 思维+模拟
class Solution {
public:
vector threeEqualParts(vector& a) {
int sum=0;
for(auto x:a) sum+=x;
if(sum%3!=0) return {-1,-1}; //如果1的个数不能均分为3份 则无解
if(sum==0) return {0,2}; //如果序列里没有1 则任意分
//把f定位到第1个1出现的位置 s定位到第part+1个1出现位置 t定位到第part*2+1个1出现位置
//也就是把1均分成3段
int part=sum/3;
int f=0,s=0,t=0,cnt=0;
for(int i=0;i
1800. 最大升序子数组和 - 简单 - dp
dp
class Solution {
public:
int maxAscendingSum(vector& a) {
int n=a.size();
vectorf(n);
int res=a[0];
f[0]=a[0];
//f[i]为以元素i为结尾时可得的子数组最大值
for(int i=1;ia[i-1]) f[i]=max(a[i],f[i-1]+a[i]);
else f[i]=a[i];
res=max(res,f[i]);
}
return res;
}
};
模拟
class Solution {
public:
int maxAscendingSum(vector& a) {
int n=a.size();
int res=a[0],sum=a[0];
for(int i=1;ia[i-1]) sum+=a[i];
else sum=a[i];
res=max(res,sum);
}
return res;
}
};
870. 优势洗牌 - 中等 - 田忌赛马 - 大顶堆
class Solution {
public:
vector advantageCount(vector& nums1, vector& nums2) {
priority_queue q;//默认大顶堆
for(auto &x:nums1) q.push(x);
vector idx(nums2.size());
iota(idx.begin(),idx.end(),0);
sort(idx.begin(),idx.end(),[&](int i,int j){return nums2[i]>nums2[j];});//数组2用下标从大到小排序
vector ans(nums1.size(),-1);
for(auto i:idx)
if(q.top()>nums2[i])
{
ans[i]=q.top();
q.pop();
}
for(auto &x:ans)
if(x==-1) x=q.top(), q.pop();
return ans;
}
};
class Solution {
public:
vector advantageCount(vector& a, vector& b) {
int n=a.size();
vector>g(n,vector(2));
for(int i=0;ia,vectorb){
return a[1]res(n,-1);
vectorv;
for(int i=0,j=0;ig[j][1])res[g[j][0]]=a[i],j++;
else v.push_back(a[i]);
int cnt=0;
for(auto &x:res)
if(x==-1)x=v[cnt++];
return res;
}
};
856. 括号的分数 - 中等 - 思维
class Solution {
public:
int scoreOfParentheses(string s) {
int res=0,cnt=0;
for(int i=0;i
801. 使序列递增的最小交换次数 - 困难 - dp
class Solution {
public:
int minSwap(vector& nums1, vector& nums2) {
int n = nums1.size();
int a = 0, b = 1;
for (int i = 1; i < n; i++) {
int at = a, bt = b;
a = b = n;
if (nums1[i] > nums1[i - 1] && nums2[i] > nums2[i - 1]) {
a = min(a, at);
b = min(b, bt + 1);
}
if (nums1[i] > nums2[i - 1] && nums2[i] > nums1[i - 1]) {
a = min(a, bt);
b = min(b, at + 1);
}
}
return min(a, b);
}
};
1790. 仅执行一次字符串交换能否使两个字符串相等 - 简单
思路:
标定起始不相同位st和末尾不相同位ed 最后交换这两个位置的字母
如果交换完相同,说明仅执行一次交换可以使两字符串相等
class Solution {
public:
bool areAlmostEqual(string s1, string s2) {
int n=s1.size();
if(s1.size()!=s2.size()) return false;
int st=-1,ed=-1;
for(int i=0;i
817. 链表组件 - 中等 - 哈希表
set.emplace() 是向set容器中插入值
题意:
在一段链表里找连续段数 例如链表1—2—3—4
nums[ 1,3,4 ] 因为1是一段 3-4是一段 所以结果为2
思路:
用哈希表set存nums出现的结点
遍历链表,如果链表中存在set里出现的值,且是开始结点,res++
如果遍历到该结点nums中不存在,则截断
class Solution {
public:
int numComponents(ListNode* head, vector& nums)
{
setmp;
for(auto n:nums)
{
mp.emplace(n);
}
int res=0;
bool f=true;
while(head!=NULL)
{
if(mp.count(head->val))
{
if(f) f=false,res++;
}else f=true;
head=head->next;
}
return res;
}
};
769. 最多能完成排序的块 - 中等 - 贪心
题意:
给定一个长度为 n 的整数数组 arr ,它表示在 [0, n - 1] 范围内的整数的排列。
我们将 arr 分割成若干 块 (即分区),并对每个块单独排序。将它们连接起来后,使得连接的结果和按升序排序后的原数组相同。
返回数组能分成的最多块数量。
思路:
由于 arrarr 是 [0,..,n-1]的一个排列,若已遍历过的数中的最大值 mx 与当前遍历到的下标 i 相等,说明可以进行一次分割,累加答案
class Solution {
public:
int maxChunksToSorted(vector& a) {
int m=0,res=0;
for(int i=0;i
940. 不同的子序列 II - 困难 - dp
题意:
给定一个字符串 s,计算 s 的 不同非空子序列 的个数。因为结果可能很大,所以返回答案需要对 10^9 + 7 取余 。
字符串的 子序列 是经由原字符串删除一些(也可能不删除)字符但不改变剩余字符相对位置的一个新字符串。
思路:
为什么 之前的curAns=新增的newcount呢?
相当于新增的这个字母本身+跟之前的组合
看第三步:之前的组合是 a、b、ab 则新增的就是 ac、bc、abc 再加上本身 c
因此curAns=newcount
class Solution {
public:
int distinctSubseqII(string s) {
int mod=(int)1e9 + 7;
int n=s.length();
vectorpre(26);
int curAns=1;
for (int i=0; i
1441. 用栈操作构建数组 - 中等ac - 指针
思路:
从1~n遍历
如果能对的上 输出Push 并移动a数组的指针
如果对不上 说明先Push再Pop 不移动指针 继续跟下一个数比较
如果指针越界 则跳出循环
class Solution {
public:
vector buildArray(vector& a, int n) {
int cnt=0;
vectors;
for(int i=1;i<=n;i++)
{
if(cnt>a.size()-1) break;
if(a[cnt]==i) s.push_back("Push"),cnt++;
else if(a[cnt]!=i) s.push_back("Push"),s.push_back("Pop");
}
return s;
}
};
886. 可能的二分法 - 中等 - 二分图模板题
dfs:
class Solution {
public:
static const int N=20010,M=N<<1;//N是点的个数 M是边的条数 因为是无向图 所以边要双倍
int h[N],e[M],ne[M],idx;
int st[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool dfs(int u,int c)
{
st[u]=c;//给这个点染色
for(int i=h[u];~i;i=ne[i])//遍历这个点相邻的点
{
int j=e[i];
if(!st[j])//如果该点未染色 递归染色
{
if(!dfs(j,3-c)) return false;//实现1、2两种颜色的转换
}
else if(st[j]==st[u]) return false;//如果染过色且染过的色和相邻点相同则不能二分
}
return true;
}
bool possibleBipartition(int n, vector>& dis) {
memset(h,-1,sizeof h);
for(auto p:dis)
{
int a=p[0],b=p[1];
add(a,b);
add(b,a);
}
for(int i=1;i<=n;i++)
if(!st[i])
if(!dfs(i,1)) return false;//如果没有染色成功 则说明无法二分图
return true;
}
};
bfs:
class Solution {
public:
static const int N=20010,M=N<<1;//N是点的个数 M是边的条数 因为是无向图 所以边要双倍
typedef pair PII;//<点的编号,颜色>
int h[N],e[M],ne[M],idx;
int st[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool bfs(int u)
{
PII q[N];
int hh=0,tt=0;
q[0]={u,1};
st[u]=1;
while(hh<=tt)
{
auto t=q[hh++];
int v=t.first,c=t.second;
for(int i=h[v];~i;i=ne[i])
{
int j=e[i];
if(!st[j])//如果相邻点未染色 则染上相反颜色并入队
{
st[j]=3-c;
q[++tt]={j,3-c};
}
else if(st[j]==c) return false;
}
}
return true;
}
bool possibleBipartition(int n, vector>& dis) {
memset(h,-1,sizeof h);
for(auto p:dis)
{
int a=p[0],b=p[1];
add(a,b);
add(b,a);
}
for(int i=1;i<=n;i++)
if(!st[i])
if(!bfs(i)) return false;//如果没有染色成功 则说明无法二分图
return true;
}
};
904. 水果成篮 - 中等 - 滑动窗口+哈希表计数
思路:
维护一个窗口 如果窗口内水果种类>2 则删掉开头的一种水果
每次循环 取最大值
class Solution {
public:
int totalFruit(vector& f) {
int res=0,t=0;
unordered_mapmp;
for(int i=0;i2)
{
int y=f[t++];
if(--mp[y]==0) mp.erase(y);//一旦窗口里水果种类>2 则删掉开头的一种水果
}
res=max(res,i-t+1);
}
return res;
}
};
class Solution {
public int totalFruit(int[] fruits) {
Map cnt = new HashMap<>();
int ans = 0;
for (int i = 0, j = 0; i < fruits.length; ++i) {
int x = fruits[i];
cnt.put(x, cnt.getOrDefault(x, 0) + 1);
while (cnt.size() > 2) {
int y = fruits[j++];
cnt.put(y, cnt.get(y) - 1);
if (cnt.get(y) == 0) {
cnt.remove(y);
}
}
ans = Math.max(ans, i - j + 1);
}
return ans;
}
}
902. 最大为 N 的数字组合 - 困难 - 数位dp
class Solution {
public int atMostNGivenDigitSet(String[] digits, int n) {
char[] nc = String.valueOf(n).toCharArray();
int result = 0, ncl = nc.length, dl = digits.length;
for (int i = 1; i < ncl; i++) result += Math.pow(dl, i); // 先对【非最高位】的其他位,可组装的数字进行统计
for (int i = 0; i < ncl; i++) {
boolean compareNext = false; // 是否需要对比下一个数字
for (String digit : digits) {
char dc = digit.charAt(0); // 将String转换为char
if (dc < nc[i]) result += Math.pow(dl, ncl - i - 1);
else {
if (dc == nc[i]) compareNext = true; break;
}
}
if (!compareNext) return result;
}
return ++result; // 如果到最后1位依然满足compareNext,因为最后1位无法再向后对比了,所以最终结果+1
}
}
1700. 无法吃午餐的学生数量 - 简单 - 模拟
思路:
统计学生喜欢吃的三明治种类
因为三明治的顺序不能动
遍历三明治 如果有一种三明治大家都不喜欢 那么这个三明治卡在栈顶 后面的人都吃不了
直接返回后面没吃到的人就可以了
class Solution {
public int countStudents(int[] stu, int[] san) {
int[] cnt=new int[2];
for(int x:stu) cnt[x]++;
for(int i=0;i
779. 第K个语法符号 - 中等 - 思维+递归+位运算
思路:
力扣
根据图可以发现:每个位置的值取决于自己的父结点
- 如果是左孩子则与父结点值相同
- 如果是右孩子则和父节点相反
如果是第一层,则返回0,否则
- 求它(n,k)父节点的位置,就是(n-1,(k+1)/2)这个意思是k/2向上取整
- 接着判断是左孩子还是右孩子:如果k是奇数,则和父节点相同,否则相反
- 也就是1^(k%2) :如果k是奇数 则1异或1为0
- 1^(k%2)^kthGrammar(n-1,(k+1)/2); 0异或任何数都不改变值
- 也就是如果k是奇数 即左孩子 值和父节点相同
class Solution {
public int kthGrammar(int n, int k) {
return n==1?0:(k%2)^1^kthGrammar(n-1,(k+1)/2);
}
}
901. 股票价格跨度 - 中等 - 单调栈
思路:
本题其实就是要求左边离自己最近的比自己大的价格的距离
例如:[100, 80, 60, 70, 60, 75, 85]
答案:[1, 1, 1, 2, 1, 4, 6]
所以利用单调栈
查询某个价格时,把比它小的价格都pop掉,并累加这些价格的w
用单调栈维护一个单调递减的价格序列,并且对于每个价格,存储一个 w 表示它离上一个价格之间(即最近的一个大于它的价格之间)的天数。如果是栈底的价格,则存储它本身对应的天数。
- 例如 [11, 3, 9, 5, 6, 4, 7] 对应的单调栈为 (11, weight=1), (9, weight=2), (7, weight=4)。
当我们得到了新的一天的价格,例如 10,我们将所有栈中所有小于等于 10 的元素全部取出,将它们的 w 进行累加,再加上 1 就得到了答案。在这之后,我们把 10 和它对应的 w 放入栈中,得到 (11, weight=1), (10, weight=7)
class StockSpanner {
Deque p,day;
public StockSpanner() {
p=new LinkedList<>();
day=new LinkedList<>();
}
public int next(int price) {
int w=1; //包括今天
while(!p.isEmpty()&&p.peek()<=price)
{
p.pop();
w+=day.pop();
}
p.push(price);
day.push(w);
return w;
}
}
1235. 规划兼职工作 - 困难 - dp+二分
class Solution {
public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
int n = profit.length;
int[][] jobs = new int[n][3];
for (int i = 0; i < n; ++i) {
jobs[i] = new int[] {startTime[i], endTime[i], profit[i]};
}
Arrays.sort(jobs, (a, b) -> a[1] - b[1]);
int[] dp = new int[n + 1];
for (int i = 0; i < n; ++i) {
int j = search(jobs, jobs[i][0], i);
dp[i + 1] = Math.max(dp[i], dp[j] + jobs[i][2]);
}
return dp[n];
}
private int search(int[][] jobs, int x, int n) {
int left = 0, right = n;
while (left < right) {
int mid = (left + right) >> 1;
if (jobs[mid][1] > x) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}
1768. 交替合并字符串 - 简单 - 模拟string
class Solution {
public String mergeAlternately(String s1, String s2) {
StringBuilder s=new StringBuilder();
int n1=s1.length(),n2=s2.length();
int l=0,r=0,cnt=1;
while(l
915. 分割数组 - 中等 - 思维
题意:
给定一个数组 nums ,将其划分为两个连续子数组 left 和 right, 使得:
- left 中的每个元素都小于或等于 right 中的每个元素。
- left 和 right 都是非空的。
- left 的长度要尽可能小。
在完成这样的分组后返回 left 的 长度
思路:
记录left数组的最大值 如果当前元素小于left数组的最大值 记录下标
例如:
[5,0,3,6,2,8,7] 随时更新左数组的最大值
class Solution {
public int partitionDisjoint(int[] a) {
if(a.length==0) return 0;
int leftMax=a[0];
int max=a[0];
int idx=0;
//如果当前元素小于左边数组的最大值时,将分界点的位置更新为当前元素的位置
for (int i=0;i
934. 最短的桥 - 中等 - dfs+bfs
思路:
用dfs把第一个岛屿先标成2
初始化dist数组全为-1
另一个岛屿的dist数组全为0
用bfs拓展另一个岛屿 一旦拓展到另一个岛屿返回dist[i][j];
最后结果-1
class Solution {
int m,n;
int[][] dist;//不能在这里初始化
int[] dx=new int[]{-1,0,1,0},dy=new int[]{0,1,0,-1};
public int shortestBridge(int[][] g)
{
m=g.length;
n=g[0].length;
dist=new int[m][n];
int f=1;
for(int i=0;i=m||b<0||b>=n) continue;
if(g[a][b]==2||g[a][b]==0) continue;
dfs(a,b,g);
}
}
public int bfs(int[][]g)
{
Queue q=new LinkedList<>();
for(int i=0;i=m||b<0||b>=n) continue;
if(dist[a][b]!=-1) continue;
dist[a][b]=dist[x][y]+1;
q.offer(new int[] {a,b});
if(g[a][b]==2) return dist[a][b];
}
}
return -1;
}
}
862. 和至少为 K 的最短子数组 - 困难 - 双向单调队列+前缀和
class Solution {
public int shortestSubarray(int[] nums, int k) {
int n=nums.length;
long[] sum=new long[n+1];
for(int i=0;i q=new ArrayDeque<>();
int ans=n+1;//ans记录满足要求的最小子串长度
for(int i=0;i<=n;i++)
{
while(!q.isEmpty()&&sum[i]-sum[q.peek()]>=k)
ans=Math.min(ans,i-q.poll()); //当满足X-sum[队头]≥k 此时的ans就是最优解了
//有最优解就可以扔掉队头了 因为后面再满足该条件 ans肯定比现在要大
//维护前缀和单调递增队列
while(!q.isEmpty()&&sum[i]<=sum[q.peekLast()])
q.pollLast();
q.offer(i);
}
return ans>n? -1:ans;
}
}
1822. 数组元素积的符号 - 简单ac
class Solution {
public int arraySign(int[] nums) {
int sum=0;
for(int x:nums)
{
if(x==0) return 0;
if(x<0) sum++;
}
if(sum%2==1) return -1;
return 1;
}
}
907. 子数组的最小值之和 - 中等 - dp+单调栈
class Solution {
//动态规划 dp[i]:a[i] 为右边界的min总和
public int sumSubarrayMins(int[] arr)
{
int len=arr.length;
int res=0;
int mod=1000000007;
int[] dp= new int[len];
dp[0]=arr[0];
Deque st=new LinkedList<>();
for(int i=0; iarr[i]) st.pop();//保证单调递增 找离它最近的比它小的值
if(!st.isEmpty())
{
int j=st.peek();
dp[i]=dp[j]+(i - j)*arr[i]; //j+1~i这一段以a[i]为最小值 0~j这一段以a[j]为最小值
}else
dp[i]=(i + 1)*arr[i]; //以a[i]为右边界的子数组都是a[i]为最小值
res=(res+dp[i])%mod;//累加dp得到结果
st.push(i);
}
return res;
}
}
1773. 统计匹配检索规则的物品数量 - 简单 - 字符串模拟
items = ["phone","blue","pixel"]
["computer","silver","lenovo"]
["phone","gold","iphone"]
ruleKey = "color", ruleValue = "silver"
↓ ↓
idx=1 如果x.get(idx)==ruleValue 则res++
class Solution {
public int countMatches(List> items, String ruleKey, String ruleValue) {
int idx= ruleKey.equals("type")? 0:ruleKey.equals("color")? 1:2;
int res=0;
for(List x:items)
if(x.get(idx).equals(ruleValue)) res++;
return res;
}
}
784. 字母大小写全排列 - 中等 - 全排列dfs
class Solution {
List res=new ArrayList<>();
public List letterCasePermutation(String s) {
char[] ch=s.toCharArray();
dfs(ch,0);
return res;
}
public void dfs(char[] ch,int idx)
{
res.add(new String(ch));
for(int i=idx;i
481. 神奇字符串 - 中等 - 字符串+双指针+构造
class Solution {
public int magicalString(int n) {
char[] s=new char[n+2]; //因为最后一次构造可能会填2个数
s[0]=1;s[1]=s[2]=2;
char c=2;
for(int i=2,j=3;j
1662. 检查两个字符串数组是否相等 - 简单ac - 字符串模拟
class Solution {
public boolean arrayStringsAreEqual(String[] s1, String[] s2) {
StringBuilder ss1=new StringBuilder();
StringBuilder ss2=new StringBuilder();
for(String x:s1) ss1.append(x);
for(String x:s2) ss2.append(x);
String a=ss1.toString();
String b=ss2.toString();
return a.equals(b);
}
}
1620. 网络信号最好的坐标 - 中等 - 模拟
class Solution {
public int[] bestCoordinate(int[][] t, int radius) {
int[] res={0,0};
int maxx=0;
for(int i=0;i<=50;i++) //因为坐标是从小到大枚举的 所以输出的肯定是最小的字典序坐标
for(int j=0;j<=50;j++)
{
int q=0;
for(int[] x:t) //枚举坐标轴上每个点跟这些信号塔的距离
{
double s=Math.sqrt(Math.pow(i-x[0],2)+Math.pow(j-x[1],2));
if(s<=radius) q+=x[2]/(1+s);
}
if(q>maxx)
{
maxx=q;
res[0]=i;
res[1]=j;
}
}
return res;
}
}
1668. 最大重复子字符串 - 简单 - 字符串模拟
class Solution {
public int maxRepeating(String s, String word) {
String t=word;
int cnt=0;
while(s.contains(word))
{
word+=t;
cnt++;
}
return cnt;
}
}
754. 到达终点数字 - 中等 -数学思维
第一点:target正负情况是一样的,所以统一把target转化为正数
- 我们的策略就是一直向右走,直到走到的位置超过target,此时的idx=1+2+……+k>=target
- 此时超出的距离为over = idx - target
- 所以我们将之前走过的某一步x反向,使idx' = 1+2+……-x+……+k = target = idx - over
- 某一步反向也就是在idx基础上-2x,即idx' = idx-2x(因为idx是+x,而idx'是-x,两者相差2x)
- 所以over = 2x = idx - target,所以idx - target必须是偶数
- 所以我们只需要找到第一个使 idx = 1 + 2 + ... + k >= target 且 idx - target 为偶数的 k 即为答案
class Solution {
public int reachNumber(int target) {
target=Math.abs(target);
int cnt=0,idx=0;
while(idx
1106. 解析布尔表达式 - 困难 - 栈
class Solution {
public boolean parseBoolExpr(String s)
{
Deque st=new ArrayDeque<>();
for(int i=0;i0?'f':'t');break;
case '|': st.push(t>0?'t':'f');break;
case '!': st.push(f==1?'t':'f');break;
}
}
}
return st.pop()=='t';
}
}
1678. 设计 Goal 解析器 - 简单ac
class Solution {
public String interpret(String s) {
String res="";
for(int i=0;i
816. 模糊坐标 - 中等 - 字符串+枚举+指针分割
class Solution {
public List ambiguousCoordinates(String s) {
int n=s.length()-2; //去掉括号的长度
List res=new ArrayList<>();
s=s.substring(1,s.length()-1);
for(int i=1;i l=get(s.substring(0,i));
List r=get(s.substring(i));
for(String a:l)
for(String b:r)
res.add("("+a+", "+b+")");
}
return res;
}
public List get(String s)
{
List ans=new ArrayList<>();
if(s.charAt(0)!='0'||"0".equals(s)) //如果该串没有前导零 或 该串只是个0 则直接添加到结果
ans.add(s);
for(int i=1;i
1684. 统计一致字符串的数目 - 简单ac
class Solution {
public int countConsistentStrings(String s, String[] words) {
Set st=new HashSet<>();
for(int i=0;i
764. 最大加号标志 - 中等 - 暴力
思路:
从某个点开始上下左右拓展 用ans更新每个点能达到的最大阶数
class Solution {
public int orderOfLargestPlusSign(int n, int[][] min)
{
int ans=0;
int[][] g=new int[n][n];
for(int i=0;i
864. 获取所有钥匙的最短路径 - 困难 - bfs+状态压缩+位运算+最短路
class Solution {
static int N=30,K=6,INF=0x3f3f3f3f;
static int[][] dirs=new int[][]{{1,0},{-1,0},{0,-1},{0,1}};
//x y代表坐标,s代表当前钥匙状态 pos表示当前步的最短路
static int[][][] pos=new int[N][N][1< q=new ArrayDeque<>();
int m=g.length,n=g[0].length();
int key=0;
for(int i=0;i='a'&&ch<='z') key++;
}
while(!q.isEmpty())
{
int[] t=q.pollFirst();
int x=t[0],y=t[1],state=t[2];
int step=pos[x][y][state];
for(int[] dir:dirs)
{
int nx=x+dir[0],ny=y+dir[1];
if(nx<0||nx>=m||ny<0||ny>=n) continue;
char c=g[nx].charAt(ny);
if(c=='#') continue;
if((c>='A'&&c<='Z')&&(state>>(c-'A')&1)==0) continue; //如果遇到锁但是没有钥匙 跳过
int next=state; //因为state在for循环外定义的,所以不能直接更改,需要先定义变量接收
if(c>='a'&&c<='z')
next|=1<<(c-'a'); //如果是钥匙 则更新状态
if(next==(1<=pos[nx][ny][next]) continue; //如果之前有更短的走法则跳过不走
pos[nx][ny][next]=step+1;
q.offerLast(new int[]{nx,ny,next});
}
}
return -1;
}
}
1704. 判断字符串的两半是否相似 - 简单ac
class Solution {
public boolean halvesAreAlike(String s) {
int len=s.length();
String a=s.substring(0,len/2),b=s.substring(len/2);
String h="aeiouAEIOU";
int cnta=0,cntb=0;
for(int i=0;i=0) cnta++;
for(int i=0;i=0) cntb++;
return cnta==cntb;
}
}
791. 自定义字符串排序 - 中等 - 模拟
class Solution {
public String customSortString(String order, String s) {
StringBuilder res=new StringBuilder();
int[] cnt=new int[26];
for(char c:s.toCharArray()) cnt[c-'a']++;
for(char c:order.toCharArray())
while(cnt[c-'a']-->0) res.append(c);
for(char c:s.toCharArray()) if(cnt[c-'a']-->0) res.append(c);
return res.toString();
}
}
1710. 卡车上的最大单元数 - 简单ac - 自定义排序
class Solution {
public int maximumUnits(int[][] box, int truckSize) {
Arrays.sort(box,(a,b)->b[1]-a[1]); //按箱子装载数从大到小排序
int sum=0;
for(int i=0;i=box[i][0])
{
sum+=box[i][0]*box[i][1];
truckSize-=box[i][0];
}else
{
sum+=truckSize*box[i][1];
break;
}
return sum;
}
}
1732. 找到最高海拔 - 简单ac
class Solution {
public int largestAltitude(int[] gain) {
int[] a=new int[gain.length+1];
a[0]=0;
int cnt=1,sum=0;
for(int i=0;i
799. 香槟塔 - 中等 - 模拟
class Solution {
public double champagneTower(int poured, int query_row, int query_glass)
{
double[][] cup=new double[101][101];
cup[0][0]=poured; //先把所有的香槟倒到第一个杯子里
for(int i=0;i<=query_row;i++)
for(int j=0;j<=i;j++)
if(cup[i][j]>1) //如果这个杯子满了
{
double half=(cup[i][j]-1)/2.0; //把这个杯子装满之后 其他的减半流入下层
cup[i][j]=1;
cup[i+1][j]+=half;
cup[i+1][j+1]+=half;
}
return cup[query_row][query_glass];
}
}
1742. 盒子中小球的最大数量 - 简单ac
class Solution {
public int countBalls(int lowLimit, int highLimit) {
int[] cnt=new int[50];
int maxx=0;
for(int i=lowLimit;i<=highLimit;i++)
{
int sum=0;
int t=i;
while(t!=0)
{
sum+=t%10;
t/=10;
}
cnt[sum]++;
}
for(int i=0;i<=45;i++) maxx=Math.max(maxx,cnt[i]);
return maxx;
}
}
809. 情感丰富的文字 - 中等 - 双指针计数
class Solution {
public int expressiveWords(String s, String[] words) {
int res=0;
for(String x:words)
if(check(s,x)) res++;
return res;
}
public boolean check(String s,String x)
{
int i=0,j=0;
while(i
1752. 检查数组是否经排序和轮转得到 -简单ac - 自写暴力法
class Solution {
public boolean check(int[] nums) {
int n=nums.length;
int[] a=new int[n];
for(int i=0;i
1779. 找到最近的有相同 X 或 Y 坐标的点 - 简单ac
class Solution {
public:
int nearestValidPoint(int x, int y, vector>& points) {
int minx=0x3f3f3f3f,idx=-1;
for(int i=0;i
1796. 字符串中第二大的数字 - 简单ac
class Solution {
public:
int secondHighest(string s) {
setst;
for(int i=0;i
class Solution {
public:
int secondHighest(string s) {
setst;
for(int i=0;i=2)
{
auto it=st.end();
--it;
return *(--it);
}
return -1;
}
};