文章目录
第一题: 396. 旋转函数
LeetCode: 396. 旋转函数
描述:
给定一个长度为 n 的整数数组 nums 。
假设 arrk 是数组 nums 顺时针旋转 k 个位置后的数组,我们定义 nums 的 旋转函数 F 为:
F(k) = 0 * arrk[0] + 1 * arrk[1] + ... + (n - 1) * arrk[n - 1]
返回 F(0), F(1), ..., F(n-1)
中的最大值 。
生成的测试用例让答案符合 32 位 整数。
解题思路:
F(0) = 0*A[0]+1*A[1]+2*A[2]+3*A[3]
F(1) = 0*A[3]+1*A[0]+2*A[1]+3*A[2]
F(2) = 0*A[2]+1*A[3]+2*A[0]+3*A[1]
F(3) = 0*A[1]+1*A[2]+2*A[3]+3*A[0]
F(1)-F(0) = A[0]+A[1]+A[2]-3*A[3]
F(2)-F(1) = A[0]+A[1]+A[3]-3*A[2]
F(3)-F(2) = A[0]+A[2]+A[3]-3*A[1]
- 令
sum = A[0]+A[1]+A[2]+A[3]
F(3) - F(2) = sum - 4 * A[1]
F(2) - F(1) = sum - 4 * A[2]
F(1) - F(0) = sum - 4 * A[3]
F(n) - F(n-1) = sum - len * A(len - n)
代码实现:
class Solution {
public int maxRotateFunction(int[] nums) {
int sum = 0;
int max = 0;
for(int i = 0; i < nums.length; i++) {
sum += nums[i];// 求 Sum
max += i * nums[i]; // 求F(0)
}
int tmp = max;
for(int i = 1; i < nums.length; i++) {
tmp += sum - nums.length * nums[nums.length - i]; // F(n) - F(n-1) = sum - len * A(len - n)
max = Math.max(tmp,max);
}
return max;
}
}
第二题: 397. 整数替换
LeetCode: 397. 整数替换
描述:
给定一个正整数 n ,你可以做如下操作:
- 如果 n 是偶数,则用 n / 2替换 n 。
- 如果 n 是奇数,则可以用 n + 1或n - 1替换 n 。
返回 n 变为 1 所需的 最小替换次数 。
解题思路:
- 如果是偶数, 那么就直接
/2
- 如果是奇数
- 首先判断是否为连续的1, 连续1, 就
+1
- 单个1, 就
-1
- 特殊的3的情况, 直接返回
次数+2
;
代码实现:
class Solution {
public int integerReplacement(int n) {
long num = n;
int res = 0;
while(num > 1) {
if(num == 3) return res + 2;
if(num % 2 == 0){
num/=2;
}else{
if((num & 3) == 1) num--;
else num++;
}
res++;
}
return res;
}
}
第三题: 398. 随机数索引
LeetCode: 398. 随机数索引
描述:
给你一个可能含有 重复元素 的整数数组 nums ,请你随机输出给定的目标数字 target 的索引。你可以假设给定的数字一定存在于数组中。
实现 Solution
类:
Solution(int[] nums)
用数组 nums 初始化对象。int pick(int target)
从 nums 中选出一个满足nums[i] == target
的随机索引 i 。如果存在多个有效的索引,则每个索引的返回概率应当相等。
解题思路:
- 这里使用哈希表解题的思路.
- key记录当前的数值, value使用List记录所有值为value的下标
- 在
pick
方法的时候, 获取到存放下标的 List , 然后使用random函数, 随机获取下标, 然后返回.
代码实现:
class Solution {
Random random;
Map<Integer,List<Integer>> map = new HashMap();
public Solution(int[] nums) {
random = new Random();
for(int i = 0; i < nums.length; i++) {
if(map.containsKey(nums[i])){
map.get(nums[i]).add(i);
}else{
List<Integer> list = new ArrayList<>();
list.add(i);
map.put(nums[i],list);
}
}
}
public int pick(int target) {
List<Integer> list = map.get(target);
return list.get(random.nextInt(list.size()));
}
}
第四题: 451. 根据字符出现频率排序
LeetCode: 451. 根据字符出现频率排序
描述:
给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。
返回 已排序的字符串 。如果有多个答案,返回其中任何一个
解题思路:
- 这里首先使用一个数组, 来对字符串中字符出现的次数进行计算.
- 在使用一个优先级队列, 堆顶存放次数较多的字符.
- 最后进行拼接. 每次弹出堆顶元素.
- 拼接好之后进行返回.
代码实现:
class Solution {
public String frequencySort(String s) {
int[] count = new int[128];
PriorityQueue<Integer> pq = new PriorityQueue<>((o1,o2)->count[o2] - count[o1]);
for(char ch : s.toCharArray()) count[ch]++;
for(int i = 0; i < 128; i++) {
if(count[i] > 0) {
pq.add(i);
}
}
StringBuilder res = new StringBuilder();
while(!pq.isEmpty()) {
int top = pq.poll();
for(int i = 0; i < count[top]; i++) {
res.append((char)top);
}
}
return res.toString();
}
}
第五题: 454. 四数相加 II
LeetCode: 454. 四数相加 II
描述:
给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
解题思路:
- 这里使用两两遍历的方式.
- 首先对
nums1
,nums2
进行遍历, 每次将遍历到的元素求和, 然后放入哈希表中.key
为对应的和,value
为对应和出现的次数- 再去遍历
nums3
和nums4
, 每次将遍历到的和加上负号, 在哈希表中去找, 如果存在, 表示可以和为0, 那么就得到对应的value值, 然后加到结果中.
代码实现:
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer,Integer> map = new HashMap<>();
int ret = 0;
int res = 0;
for (int val1 : nums1){
for (int val2 : nums2) {
ret = val1 + val2;
if(map.containsKey(ret)) {
map.put(ret,map.get(ret) + 1);
}else{
map.put(ret,1);
}
}
}
for (int val1 : nums3){
for (int val2 : nums4) {
ret = val1 + val2;
if (map.containsKey(0 - ret)) {
res += map.get(0 - ret);
}
}
}
return res;
}
}
第六题: 476. 数字的补数
LeetCode: 476. 数字的补数
描述:
对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。
- 例如,整数 5 的二进制表示是 “101” ,取反后得到 “010” ,再转回十进制表示得到补数 2 。
给你一个整数 num ,输出它的补数。
解题思路:
- 这里使用位运算.
- 首先去记录这个数字一共占了多少为. 循环去判断这个数是否等于0, 不等于的时候去右移1个.
- 每次移动的时候, 再去用一个数字, 在每位都置为1
- 例如, 5, 二进制为 101, 占了3个位置. 然后就用另一个数字每位为1,
111
, 用这个数字去和 5 进行异或操作.- 异或之后, 就是补数.
代码实现:
class Solution {
public int findComplement(int num) {
int tmp = num;
int ret = 0;
while(tmp > 0) {
tmp >>= 1;
ret = (ret << 1) | 1;
}
return ret ^ num;
}
}