将整数减少到零需要的最少操作数
题目描述
给你一个正整数 n ,你可以执行下述操作 任意 次:
n 加上或减去 2 的某个 幂
返回使 n 等于 0 需要执行的 最少 操作数。
如果 x == 2i 且其中 i >= 0 ,则数字 x 是 2 的幂。
样例
样例输入
n = 39
n = 54
样例输出
3
解释:我们可以执行下述操作:
n 加上 20 = 1 ,得到 n = 40 。
n 减去 23 = 8 ,得到 n = 32 。
n 减去 25 = 32 ,得到 n = 0 。
可以证明使 n 等于 0 需要执行的最少操作数是 3 。
3
解释:我们可以执行下述操作:
n 加上 21 = 2 ,得到 n = 56 。
n 加上 23 = 8 ,得到 n = 64 。
n 减去 26 = 64 ,得到 n = 0 。
使 n 等于 0 需要执行的最少操作数是 3 。
提示
- 1 < = n < = 1 0 5 1 <= n <= 10^5 1<=n<=105
思路
二的某个幂,那不就是说明了,这个题需要用二进制来做,然后求当前是+或者-能够使得当前二进制数中的1数量减到最少,因为1111
这种类型的存在,+1会比-1使得当前二进制数中的1数量减少。还有这二个测试用例很好,通过测试用例就知道当+1与-1的结果都一致,需要选择+1.
代码实现
class Solution {
public int minOperations(int n) {
int ans = 0;
while(n > 0){
ans++;
int s1 = lowbit(n + (n&(-n)));
int s2 = lowbit(n - (n&(-n)));
if(s2 == 0) break;
if(s1 <= s2) n += (n&(-n));
else n -= (n&(-n));
}
return ans;
}
// 求出当前数的二进制形式中有多少个1.
private int lowbit(int x){
int index = 0;
while(x > 0){
x -= x&(-x);
index++;
}
return index;
}
}
最大平均通过率
题目描述
一所学校里有一些班级,每个班级里有一些学生,现在每个班都会进行一场期末考试。给你一个二维数组 classes ,其中 classes[i] = [passi, totali] ,表示你提前知道了第 i 个班级总共有 totali 个学生,其中只有 passi 个学生可以通过考试。
给你一个整数 extraStudents ,表示额外有 extraStudents 个聪明的学生,他们 一定 能通过任何班级的期末考。你需要给这 extraStudents 个学生每人都安排一个班级,使得 所有 班级的 平均 通过率 最大 。
一个班级的 通过率 等于这个班级通过考试的学生人数除以这个班级的总人数。平均通过率 是所有班级的通过率之和除以班级数目。
请你返回在安排这 extraStudents 个学生去对应班级后的 最大 平均通过率。与标准答案误差范围在 10-5 以内的结果都会视为正确结果。
样例
样例输入
classes = [[1,2],[3,5],[2,2]], extraStudents = 2
classes = [[2,4],[3,9],[4,5],[2,10]], extraStudents = 4
样例输出
0.78333
解释:你可以将额外的两个学生都安排到第一个班级,平均通过率为 (3/4 + 3/5 + 2/2) / 3 = 0.78333 。
0.53485
提示
- 1 < = c l a s s e s . l e n g t h < = 1 0 5 1 <= classes.length <= 10^5 1<=classes.length<=105
- c l a s s e s [ i ] . l e n g t h = = 2 classes[i].length == 2 classes[i].length==2
- 1 < = p a s s i < = t o t a l i < = 1 0 5 1 <= passi <= totali <= 10^5 1<=passi<=totali<=105
- 1 < = e x t r a S t u d e n t s < = 1 0 5 1 <= extraStudents <= 10^5 1<=extraStudents<=105
思路
贪心思想,需要把班级通过一种特殊的方式排序,这个特殊的排序归责就是加入一个通过的学生对班级的平均通过率提升最大来排序。因为需要有多次取按照指定排序规则中的最大值,所以优先队列最为合适。
代码实现
class Solution {
public double maxAverageRatio(int[][] classes, int extraStudents) {
int len = classes.length;
PriorityQueue<double[]> queue = new PriorityQueue<>((a, b) -> {
double x = (a[0] + 1) / (a[1] + 1) - a[0] / a[1];
double y = (b[0] + 1) / (b[1] + 1) - b[0] / b[1];
if(x > y) return -1;
if(y < x) return 1;
return 0;
});
for(int[] c : classes) queue.offer(new double[]{c[0], c[1]});
while(extraStudents-- > 0){
double[] cur = queue.poll();
cur[0] += 1.0;
cur[1] += 1.0;
queue.offer(cur);
}
double ans = 0;
while(!queue.isEmpty()){
double[] c = queue.poll();
ans += (c[0] / c[1]);
}
return ans / len;
}
}