题目来源
梗佬算法社区链接:https://bbs.youkuaiyun.com/forums/Suanfa?typeId=86729
刷题总帖链接:https://bbs.youkuaiyun.com/topics/607219407
7月2日 第一天
一、三个数的最大乘积
题目链接:https://leetcode.cn/problems/maximum-product-of-three-numbers/
思路:
最大三个数的乘积或 最小两数与最大数的乘积
class Solution {
public int maximumProduct(int[] nums) {
Arrays.sort(nums); //升序排序
return Math.max(nums[0]*nums[1]*nums[nums.length-1],nums[nums.length-3]*nums[nums.length-2]*nums[nums.length-1]);
}
}
二、有多少小于当前的数字
题目链接:https://leetcode.cn/problems/how-many-numbers-are-smaller-than-the-current-number/
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int[] nn=new int[nums.length];
for (int i = 0; i < nums.length; i++) {
int num=0;
for (int j = 0; j < nums.length ; j++) {
if (nums[i]>nums[j]&& j != i) num++;
}
nn[i]=num;
}
return nn;
}
}
三、使数组唯一的最小增量
题目链接:https://leetcode.cn/problems/minimum-increment-to-make-array-unique/
第一反应是用 HashSet 查重
class Solution {
public int minIncrementForUnique(int[] nums) {
Set set=new HashSet<>();
int num=0;
for (int i=0;i<nums.length;i++){
if (!set.contains(nums[i])){
set.add(nums[i]);
}
else if (set.contains(nums[i])){
while (set.contains(nums[i])){
nums[i]=nums[i]+1;
num++;
}
set.add(nums[i]);
}
}
return num;
}
}
但超时了~~
换种思路:
先排序,在…看代码吧,直接
class Solution {
public int minIncrementForUnique(int[] nums) {
int num = 0;
Arrays.sort(nums);
for (int i = 0; i < nums.length-1; i++) {
while (nums[i] >= nums[i + 1]) {
nums[i + 1] += 1;
num++;
}
}
return num;
}
}
四、B - 上升的沙子
题目链接:https://codeforces.com/contest/1698/problem/B
思路:求数组里面最多有多少个沙子,能在对 任意选中的k个数进行无数次+1后 还是最高
k=1 时特解 ;k>=2 时,拣选ķ连续的一堆沙子对于太高的桩的最大数量只有两种结果 不变和减少 ,所以直接按原来的数组计算
import java.util.*;
import java.lang.*;
public class Main {
public static void main(String[] args) {
Scanner mc = new Scanner(System.in);
int t = mc.nextInt();
for (int i = 0; i < t; i++) {
int nums=0;
int n = mc.nextInt();
int k = mc.nextInt();
int[] num=new int[n];
for (int j=0;j<n;j++){
num[j]=mc.nextInt();
}
if (k==1) {
System.out.println((n-1)/2);
continue;
}
else for (int j=1;j<num.length-1;j++){
if (num[j]>num[j-1]+num[j+1])
nums++;
}
System.out.println(nums);
}
}
}
7月3日 第二天
一、二分查找
题目链接: https://leetcode.cn/problems/binary-search/
思路:mid 记录下标
class Solution {
public int search(int[] nums, int target) {
int left=0;
int right=nums.length-1;
while (left<=right){
int mid=(right+left)>>1;
//位运算加速,相当于 mid=(left+right)/2
if (nums[mid]==target){ //二分模板
return mid;
}
else if (nums[mid]>target)
right=mid-1;
else left=mid+1;
}
return -1;
}
}
二、找出数组排序后的目标下标
题目链接:https://leetcode.cn/problems/find-target-indices-after-sorting-array/
思路:HashSet 查重,判断是否输出数组
再遍历判断
class Solution {
public List<Integer> targetIndices(int[] nums, int target) {
Set<Integer> set=new HashSet<>();
List<Integer> list=new ArrayList<>();
Arrays.sort(nums); //升序
for (int i:nums)
set.add(i);
if (!set.contains(target))
return list;
else for (int j=0;j<nums.length;j++){
if (nums[j]==target)
list.add(j);
}
return list;
}
}
三、寻找重复数
题目链接: https://leetcode.cn/problems/find-the-duplicate-number/
思路:将nums数组内的每个数 减去1 ,对应到vis 数组下标 ,并记录数字出现次数,最后遍历vis 将大于1 的数对应下标加回1,就是原数
例:nums[3,1,1] 经操作后得 vis[2,0,1] 即为出现次数 ,其 vis 对于下标
[0,1,2] 进行加1 ,就是原来的 数字。
class Solution {
public int findDuplicate(int[] nums) {
int[] vis=new int[nums.length];
for (int i=0;i<nums.length;i++){
vis[nums[i]-1]+=1;
}
for (int j=0;j<nums.length;j++){
if (vis[j]>1)
return j+1;
}
return 0;
}
}
四、二进制双端队列
题目链接: https://codeforces.com/problemset/problem/1692/E
思路:任意进行 删除头或尾 的操作,可重复进行删除头 操作,只要最后操作数 最少
不妨换总思路 ,即求 所选数组区间 最长
import java.util.*;
import java.lang.*;
public class Main {
public static void main(String[] args) {
Scanner mc = new Scanner(System.in);
int k = mc.nextInt();
while (k-- != 0) {
int n = mc.nextInt();
int num = mc.nextInt();
int[] nums = new int[n];
for (int j = 0; j < n; j++) {
nums[j] = mc.nextInt();
}
int t = 0; //最大区间长
int left = 0; //所选区间左下标
int right =0; //所选区间右下标
int ans=0;
if (sum(nums)==num){ //特判1
System.out.println("0");
continue;
}
if (sum(nums)<num){ //特判2
System.out.println("-1");
continue;
}
for (;right<n;right++){
ans+=nums[right];
while (ans>num){
ans-=nums[left];
left++;
}
if (ans==num&&right-left+1>t){
t=right-left+1; //最大区间长
}
}
System.out.println(n-t); //操作数
}
}
static int sum(int[] nums) { //求和
int ss = 0;
for (int n : nums)
ss += n;
return ss;
}
}
7月4日 第三天
一、区域和检索——数组不可变
题目链接: https://leetcode.cn/problems/range-sum-query-immutable/
思路:
数组 sum 储存 前几项 num 的和
例:nums[1,2,3,4] 则 sum[0,1,3,6,10] 对应 sum下标[0,1,2,3,4] , 下标是n ,对应到 sum 的值为 nums 前 n 项和
class NumArray {
int[] sum;
public NumArray(int[] nums) {
int n = nums.length;
sum = new int[n + 1];
for (int i = 0; i < n; i++)
sum[i + 1] = sum[i] + nums[i];
}
public int sumRange(int left, int right) {
return sum[right + 1] - sum[left];
}
}
二、所有奇数长度子数组的和
题目链接: https://leetcode.cn/problems/sum-of-all-odd-length-subarrays/
思路:
数学方法
依次求每个数字的出现次数 ,即将数组以 i 为界限分为两部分,要想得到包含 i 的奇数数组,必须除 i 之后两边的 两部分取 同奇或同偶;
.
例:arr[1,4,2,5,3] ,先计算 2 出现的次数,其左数组奇数个数 为2 ,其右数组奇数个数 为2;其左数组偶数个数 为1,其右数组偶数个数 为1,
则 2 的出现次数为 2 * 2 + 1 * 1 = 5
应题目进阶要求 时间复杂度O(n) ,除此外 暴力 + 前缀和 也可
class Solution {
public int sumOddLengthSubarrays(int[] arr) {
int sum = 0;
int n=arr.length;
for (int i = 0; i < n; i++) {
int leftj = (i + 1) / 2;// 左边奇数个数的可能性
int righj = (n - i) / 2; // 右边奇数个数的可能性
int lefto = i / 2 + 1; // 左边偶数个数的可能性
int righto = (n - i - 1) / 2 + 1; // 右边偶数个数的可能性
// 计算结果
sum += arr[i] * (leftj * righj + lefto * righto);
}
return sum;
}
}
三、和相同的二元子数组
题目链接: https://leetcode.cn/problems/binary-subarrays-with-sum/
思路:滑动窗口
sum2 >= goal 操作数 与sum1 > goal 操作数 之差 为 sum2 = goal 时的情况数
class Solution {
public int numSubarraysWithSum(int[] nums, int goal) {
int left1 = 0, left2 = 0;
int right = 0;
int sum1 = 0, sum2 = 0;
int ans = 0;
for (; right < nums.length; right++) {
sum1 += nums[right];
sum2 += nums[right];
while (left1 <= right && sum1 > goal) sum1 -= nums[left1++];
while (left2 <= right && sum2 >= goal) sum2 -= nums[left2++];
ans += left2 - left1;
}
return ans;
}
}
四、买一把铲子
题目链接: https://codeforces.com/problemset/problem/732/A
import java.util.*;
import java.lang.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int k = scanner.nextInt();
int r = scanner.nextInt();
int i = 0, sum = 0;
while (++i != 0) {
sum += k;
if (sum % 10 == 0 || sum % 10 == r) {
System.out.println(i);
break;
}
}
}
}
7月5日 第四天
一、合并两个有序数组
题目链接: https://leetcode.cn/problems/merge-sorted-array/
思路:for 语句赋值
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
for (int i = m; i < m + n; i++) {
nums1[i] = nums2[i-m];
}
Arrays.sort(nums1);
}
}
二、环形链表
题目链接:https://leetcode.cn/problems/linked-list-cycle/
思路:快慢指针
让 fast 与 slow 以不同速度 移动,只要 有环 速度不同的两个 指针一定相遇
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if (head==null||head.next==null)
return false;
ListNode slow=head.next; //起点不要设置一样的
ListNode fast=head.next.next;
while (slow!=fast){
if (fast==null||fast.next==null)
return false;
slow=slow.next;
fast=fast.next.next;
}
return true;
}
}
三、三数之和
题目链接: https://leetcode.cn/problems/3sum/
思路: 遍历 + 双指针(特判,不能重复)
先升序排列
指针分别放在 i 前一位(向前移)和最后位(向后移)
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums); //升序
for (int i = 0; i < nums.length; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue; //特判1
int j = i + 1, k = nums.length - 1;
while (j < k) {
int m = nums[i] + nums[j] + nums[k];
if (m == 0) {
list.add(Arrays.asList(nums[i], nums[j], nums[k]));
while (j < k && nums[j] == nums[j + 1]) //特判2
j++;
while (j < k && nums[k] == nums[k - 1]) //特判3
k--;
j++;
k--;
}
if (m > 0)
k--;
if (m < 0)
j++;
}
}
return list;
}
}
四、Z mod X = C
题目链接:https://codeforces.com/problemset/problem/1684/B
思路:
已知 x%y=a,y%z=b,z%x=c ,a>b>c ,求 x , y , z
得:z = c ; y = z + b = c + b ; x = y + a = c + b + a .题目 只要求 输出一种可能 ,用简单方法找 特殊情况即可。
import java.util.*;
import java.lang.*;
public class Main {
public static void main(String[] args) {
Scanner mc = new Scanner(System.in);
int n = mc.nextInt();
while (n-- != 0) {
int a = mc.nextInt();
int b = mc.nextInt();
int c = mc.nextInt();
System.out.println((a+b+c)+" "+(b+c)+" "+c);
}
}
}
7月6日 第五天
一、二进制间距
题目链接:添加链接描述
class Solution {
public int binaryGap(int n) {
int j=-1,m=0;
for (int i=30;i>=0;i--){
if (((n>>i)&1)==1){ //移位 判断是否=1
if (j!=-1)
m=Math.max(m,j-i);
j=i;
}
}return m;
}
}
二、位1的个数
题目链接: https://leetcode.cn/problems/number-of-1-bits/
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int a = 0;
for (int i = 32; i > 0; i--) {
if (((n >> i) & 1) == 1)
a++;
}
return a;
}
}
三、只出现一次的数字
题目链接:https://leetcode.cn/problems/single-number/
class Solution {
public int singleNumber(int[] nums) {
int m=0;
for(int i:nums)
m^=i;
return m;
}
}
四、第 K 个不能被 n 整除
题目链接:https://codeforces.com/contest/1352/problem/C
import java.util.*;
import java.lang.*;
public class Main {
public static void main(String[] args) {
Scanner mc = new Scanner(System.in);
int t = mc.nextInt();
while (t-- != 0) {
int n = mc.nextInt();
int k = mc.nextInt();
if (k < n)
System.out.println(k);
else {
int m = k % (n - 1);
if (m == 0)
System.out.println(n * (k / (n - 1)) + m - 1);
else System.out.println(n * (k / (n - 1)) + m);
}
}
}
}
7月7日 第六天
一、分发饼干
题目链接: https://leetcode.cn/problems/assign-cookies/
class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int m=0;
int ans =0;
for (int n=0;n<g.length;n++){
for (;m<s.length;m++){
if (g[n]<=s[m]){
ans++;
m++;
break;
}
}
}
return ans;
}
}
二、心算挑战
题目链接: https://leetcode.cn/problems/uOAnQW/
思路:
先排升序 ,记录数组最后 cnt 个数中,最小奇数 最小偶数 的位置,若 sum 是偶数直接输出,否则
判断前一位的奇偶性,若为奇数就与 sum 中最小偶数交换,若为偶数就与 sum 中最小奇数交换
class Solution {
public int maxmiumScore(int[] cards, int cnt) {
int sum = 0;
int j = cards.length - cnt;
int o = cards.length - cnt;
int k = 0;
Arrays.sort(cards);
while (j < cards.length && cards[j] % 2 != 1) {
j++;
}
while (o < cards.length && cards[o] % 2 == 1) {
o++;
}
while (k++ != cnt) sum += cards[cards.length - k];
if (cnt == cards.length) {
sum = sum % 2 == 0 ? sum : 0;
}
int w = sum;
if (sum % 2 == 1) {
for (int i = cards.length - 1 - cnt; i >= 0; i--) {
if (sum % 2 != 0 && cards[i] % 2 == 0 && j < cards.length) {
sum = sum - cards[j] + cards[i];
w = sum;
break;
} else if (sum % 2 != 0 && cards[i] % 2 == 1 && o < cards.length) {
sum = sum - cards[o] + cards[i];
w = sum;
break;
} else if (sum % 2 == 1)
w = 0;
}
}
return w;
}
}
三、.保持城市天际线
题目链接:https://leetcode.cn/problems/max-increase-to-keep-city-skyline/
class Solution {
public int maxIncreaseKeepingSkyline(int[][] grid) {
int[] row=new int[grid[0].length]; //行
int[] line =new int[grid.length]; //列
int m=0;
for (int r=0;r<grid[0].length;r++){
for (int l=0;l<grid.length;l++){
row[r]=Math.max(row[r],grid[r][l]);
line[l]=Math.max(line[l],grid[r][l]);
}
}
for (int r=0;r<grid[0].length;r++){
for (int l=0;l<grid.length;l++){
m+=Math.min(row[r],line[l])-grid[r][l];
}
}
return m;
}
}