【每日一练】java版

题目来源
请添加图片描述

梗佬算法社区链接:https://bbs.csdn.net/forums/Suanfa?typeId=86729

刷题总帖链接:https://bbs.csdn.net/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;
    }
}

四、洗鞋
题目链接: https://codeforces.com/problemset/problem/1691/B

猜你喜欢

转载自blog.csdn.net/qjjspl_/article/details/125572697