给你一个非负整数数组 nums
。在一步操作中,你必须:
x
,x
需要小于或等于 nums
中 最小 的 非零 元素。nums
中的每个正整数都减去 x
。返回使 nums
中所有元素都等于0
需要的 最少 操作数。
0
元素作为x
,然后将所有元素慢慢变为0
。问题将变化为数组中存在多少个非0
的不同元素。 public int minimumOperations(int[] nums) {
Set<Integer> set=new HashSet<>();
int n=nums.length;
for (int num : nums) {
if (num != 0) set.add(num);
}
return set.size();
}
算法:贪心
时间复杂度:遍历一次数组,复杂度为
O
(
n
)
O(n)
O(n)。
给你一个正整数数组 grades
,表示大学中一些学生的成绩。你打算将 所有 学生分为一些 有序 的非空分组,其中分组间的顺序满足以下全部条件:
i
个分组中的学生总成绩 小于第 (i + 1)
个分组中的学生总成绩,对所有组均成立(除了最后一组)。i
个分组中的学生总数 小于 第 (i + 1)
个分组中的学生总数,对所有组均成立(除了最后一组)。1
,2
,3
…这样分下去,看最多能分多少组。这里相当于是一个等差数列,我们可以二分 出答案。 public int maximumGroups(int[] arr) {
int n=arr.length;
int l=0,r=100000;
while (l<r){
int mid=l+r+1>>1;
long v= (long) mid *(mid+1)/2;
if(v>n) r=mid-1;
else l=mid;
}
return r;
}
算法:贪心 脑筋急转弯 二分
时间复杂度:二分复杂度为
O
(
l
o
g
n
)
O(logn)
O(logn)。
给你一个 n
个节点的 有向图 ,节点编号为 0
到 n - 1
,每个节点 至多 有一条出边。
有向图用大小为 n
下标从 0 开始的数组 edges
表示,表示节点i
有一条有向边指向 edges[i]
。如果节点 i
没有出边,那么 edges[i] == -1
。
同时给你两个节点 node1
和 node2
。
请你返回一个从 node1
和 node2
都能到达节点的编号,使节点 node1
和节点 node2
到这个节点的距离 较大值最小化。如果有多个答案,请返回 最小
的节点编号。如果答案不存在,返回 -1
。
注意 edges
可能包含环。
node1
和node2
都能到达的节点,我们可以对两个结点分别做一次bfs
,把遇到的节点分别放到set
中。dist
数组统计到达每个点的距离,由于答案求的是较大值最小化,所以首先两个结点都能到达的结点的距离我们需要取max
。dist
进行遍历,找到两个set
都存储过的点,然后这些找到dist
最小的结点。Map<Integer,Integer> map=new HashMap<>();
int N=100010;
int[] dist=new int[N];
int ans=Integer.MAX_VALUE;
Set<Integer> s1=new HashSet<>();
Set<Integer> s2=new HashSet<>();
int jie=-1;
public int closestMeetingNode(int[] edges, int node1, int node2) {
int n=edges.length;
for (int i = 0; i <n; i++) {
add(i,edges[i]);
}
bfs(node1,true);
bfs(node2,false);
for (int i = 0; i < n; i++) {
if (s1.contains(i)&&s2.contains(i)){
if (dist[i]<ans){
ans=dist[i];
jie=i;
}
}
}
return jie;
}
void bfs(int start,boolean f){
Queue<Integer> q=new LinkedList<>();
boolean[] st=new boolean[N];
st[start]=true;
q.offer(start);
int x=0;
while (!q.isEmpty()){
int size=q.size();
while (size-->0){
int curr=q.poll();
if (f) s1.add(curr);
else s2.add(curr);
int next=map.get(curr);
dist[curr]=Math.max(x,dist[curr]);
if (next==-1||st[next]) continue;
q.offer(next);
st[next]=true;
}
x++;
}
}
void add(int a,int b){
map.put(a,b);
}
算法:BFS
时间复杂度:最坏不超过
O
(
n
)
O(n)
O(n)
给你一个 n
个节点的 有向图 ,节点编号为0
到n - 1
,其中每个节点 至多 有一条出边。
图用一个大小为 n
下标从 0 开始的数组 edges
表示,节点 i
到节点 edges[i]
之间有一条有向边。如果节点 i
没有出边,那么 edges[i] == -1
。
请你返回图中的 最长 环,如果没有任何环,请返回 -1
。
一个环指的是起点和终点是 同一个 节点的路径。
1
,所以对于之前已经访问过的点,我们不需要再以它为起点进行搜索了,否则会超时。在所有搜索到的环中取最大值。class Solution {
boolean[] st=new boolean[100010];
Map<Integer,Integer> map=new HashMap<>();
int res=0;
public int longestCycle(int[] edges) {
int n=edges.length;
for (int i = 0; i <n ; i++) {
add(i,edges[i]);
}
for (int i = 0; i < n; i++) {
if (!st[i]) bfs(i);
}
return res==0?-1:res;
}
void bfs(int start){
Queue<Integer> q=new LinkedList<>();
st[start]=true;
q.offer(start);
Map<Integer,Integer> ad=new HashMap<>();
ad.put(start,0);
int x=0;
while (!q.isEmpty()){
int size=q.size();
while (size-->0){
int curr=q.poll();
int next=map.get(curr);
if (ad.containsKey(next)){
res=Math.max(x-ad.get(next)+1,res);
}
if (next==-1||st[next]) return;
ad.put(next,x+1);
q.offer(next);
st[next]=true;
}
x++;
}
}
void add(int a,int b){
map.put(a,b);
}
}
算法:BFS
时间复杂度:每个点最多访问一次,
O
(
n
)
O(n)
O(n)
图论题不熟练,写的太慢,代码又臭又长。