leetcode--各种数据结构相关的题

news2024/7/30 9:06:09

数据结构

  • 1.数组
    • (1)找到所有数组中消失的数字(448)
    • (2)旋转图像(48)
    • (3)搜索二维矩阵 II(240)
    • (4)最多能完成排序的块(769)
  • 2.栈和队列
    • (1)用栈实现队列(232)
    • (2)最小栈(155)
    • (3)有效的括号(20)
  • 3.单调栈
    • (1)每日温度
  • 4.优先队列
    • (1)合并K个升序链表(23)
  • 5.双端队列
    • (1)滑动窗口最大值(239)
  • 6.哈希表
    • (1)两数之和(1)
    • (2)最长连续序列(128)
    • (3)直线上最多的点数
  • 7.前缀和与积分图
    • (1)区域和检索 - 数组不可变(303)
    • (2)二维区域和检索 - 矩阵不可变(304)
    • (3)和为 K 的子数组(560)
  • 8.练习
    • (1)重塑矩阵(566)
    • (2)用队列实现栈(225)
    • (3)下一个更大元素 II(503)
    • (4)存在重复元素(217)
    • (5)数组的度
    • (6)最长和谐子序列(594)
    • (7)寻找重复数(287)
    • (8)优势洗牌(870)

1.数组

(1)找到所有数组中消失的数字(448)

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]

输入:nums = [1,1]
输出:[2]
//时间空间复杂度都为O(n)
public class Solution {

    public static void main(String[] args) {
        int[] arr={4,3,2,7,8,2,3,1};
        Solution solution=new Solution();
        System.out.println(solution.findDisappearedNumbers(arr));
    }

    public List<Integer> findDisappearedNumbers(int[] nums) {
        int n= nums.length;
        boolean[] find=new boolean[n+1];//数组中出现的数将该数对应的数组位置置为true
        List<Integer> list=new ArrayList<>();
        for (int i=0;i<n;i++){
            find[nums[i]]=true;
        }
        for (int i=1;i<=n;i++){
            if (!find[i]){
                list.add(i);
            }
        }
        return list;
    }
}


//空间复杂度为O(1)
public class Solution {

    public static void main(String[] args) {
        int[] arr={4,3,2,7,8,2,3,1};
        Solution solution=new Solution();
        System.out.println(solution.findDisappearedNumbers(arr));
    }

    public List<Integer> findDisappearedNumbers(int[] nums) {
        int n= nums.length;
        List<Integer> list=new ArrayList<>();
        //遍历数组 每遇到一个数x 就让nums[x-1]增加n
        //当我们遍历到某个位置时 其中的数可能已经被增加过了 因此需要对n取模
        for (int i=0;i<n;i++){
            int x=(nums[i]-1)%n;
            nums[x]+=n;
        }
        //遍历nums 若nums[i]未大于n 就说明没有遇到过数i+1
        for (int i=0;i<n;i++){
            if (nums[i]<=n){
                list.add(i+1);
            }
        }
        return list;
    }
}

(2)旋转图像(48)

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。


对应位置交换位置,结束条件可以考虑i和j同时向内缩进,也就是一圈一圈考虑
public class Solution {

    public static void main(String[] args) {
        int[][] arr={{5,1,9,11},
                     {2,4,8,10},
                     {13,3,6,7},
                     {15,14,12,16}};
        Solution solution=new Solution();
        solution.rotate(arr);
        for (int i=0;i<arr.length;i++){
            for (int j=0;j< arr[0].length;j++){
                System.out.print(arr[i][j]+" ");
            }
            System.out.println();
        }
    }

    public void rotate(int[][] matrix) {
        int rowMin=0;//从第0行开始 起始行
        int colMin=0;//从第0列开始 起始列
        int rowMax= matrix.length-1;//第一圈可以用到的的最大行数是总行数-1
        int colMax=matrix[0].length-1;//第一圈可以用到的的最大列数是总列数-1
        //旋转完一圈开始下一圈 循环退出条件是 起始行>最大行 起始列>最大列
        while (rowMin<=rowMax&&colMin<=colMax){
            RotateOneCircle(matrix,rowMin,colMin,rowMax,colMax);
            //缩进
            rowMin++;
            colMin++;
            rowMax--;
            colMax--;
        }
    }

    //旋转一圈的方法
    private void RotateOneCircle(int[][] arr, int rowMin, int colMin, int rowMax, int colMax) {
        int temp=0;//辅助数
        //遍历旋转这一圈
        for (int j=0;j<colMax-colMin;j++){
            temp=arr[rowMin][colMin+j];
            arr[rowMin][colMin+j]=arr[rowMax-j][colMin];
            arr[rowMax-j][colMin]=arr[rowMax][colMax-j];
            arr[rowMax][colMax-j]=arr[rowMin+j][colMax];
            arr[rowMin+j][colMax]=temp;
        }
    }
}

(3)搜索二维矩阵 II(240)

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

每行的元素从左到右升序排列。
每列的元素从上到下升序排列。

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true
从数组的右上角开始遍历,如果target大于当前元素,则用当前元素下方的元素再次比较;如果target小于当前元素,
则用当前元素左边的元素再次比较;以此类推,知道找到target或者到达边界
public class Solution {

    public static void main(String[] args) {
        int[][] arr={{1,4,7,11,15},
                     {2,5,8,12,19},
                     {3,6,9,16,22},
                     {10,13,14,17,24},
                     {18,21,23,26,30}};
        int target=5;
        Solution solution=new Solution();
        System.out.println(solution.searchMatrix(arr,5));
    }

    public boolean searchMatrix(int[][] matrix, int target) {
        int m= matrix.length;
        int n=matrix[0].length-1;//表示列
        int i=0;//表示行
        while (i<m&&n>=0){
            if (target>matrix[i][n]){//target大于当前元素 比较下方元素
                i++;
            } else if (target<matrix[i][n]) {//target小于当前元素 比较左方元素
                n--;
            }else {//找到target
                return true;
            }
        }
        return false;
    }
}

(4)最多能完成排序的块(769)

给定一个长度为 n 的整数数组 arr ,它表示在 [0, n - 1] 范围内的整数的排列。
我们将 arr 分割成若干 块 (即分区),并对每个块单独排序。将它们连接起来后,使得连接的结果和按升序排序后的原数组相同。
返回数组能分成的最多块数量。

输入: arr = [4,3,2,1,0]
输出: 1
解释:
将数组分成2块或者更多块,都无法得到所需的结果。
例如,分成 [4, 3], [2, 1, 0] 的结果是 [3, 4, 0, 1, 2],这不是有序的数组。

输入: arr = [1,0,2,3,4]
输出: 4
解释:
我们可以把它分成两块,例如 [1, 0], [2, 3, 4]。
然而,分成 [1, 0], [2], [3], [4] 可以得到最多的块数。
对每个块单独排序后,结果为 [0, 1], [2], [3], [4]
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,0,2,3,4};
        Solution solution=new Solution();
        System.out.println(solution.maxChunksToSorted(arr));
    }

    public int maxChunksToSorted(int[] arr) {
        int n=arr.length;
        if (arr.length==1){
            return 1;
        }
        int maxCount=0;//可以分成的最大块数
        int preMax=0;//当前最大值
        for (int i=0;i<n;i++){
            preMax=Math.max(preMax,arr[i]);
            //如果当前最大值等于当前的i值
            if (preMax==i){
                maxCount++;//可以分块数+1
            }
        }
        return maxCount;
    }
}

2.栈和队列

(1)用栈实现队列(232)

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:

你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

public class MyQueue {

    Stack<Integer> stack1;
    Stack<Integer> stack2;

    public MyQueue() {
        stack1=new Stack<>();
        stack2=new Stack<>();
    }

    public void push(int x) {
        while (!stack2.isEmpty()){
            stack1.push(stack2.pop());
        }
        stack1.push(x);
    }

    public int pop() {
        if (stack2.isEmpty()){
            while (!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }

    public int peek() {
        if (stack2.isEmpty()){
            while (!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
        }
        return stack2.peek();
    }

    public boolean empty() {
        if (stack1.empty()&& stack2.empty()){
            return true;
        }
        return false;
    }
}


public class QueueTest {

    public static void main(String[] args) {
        MyQueue queue=new MyQueue();
        queue.push(1);
        queue.push(2);
        queue.push(3);
        //System.out.println("pop():"+queue.pop());
        System.out.println("peak():"+queue.peek());
        System.out.println("empty():"+queue.empty());
        queue.push(4);
        System.out.println("====================");
        System.out.println("pop():"+queue.pop());
        System.out.println("peak():"+queue.peek());
        System.out.println("empty():"+queue.empty());
    }

}

(2)最小栈(155)

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。

public class MinStack {

    Stack<Integer> stack;//普通栈
    Stack<Integer> minStack;//返回最小值的栈

    public MinStack() {
        stack=new Stack<>();
        minStack=new Stack<>();
        minStack.push(Integer.MAX_VALUE);
    }

    public void push(int val) {
        stack.push(val);
        //最小值栈保存当前元素加进来后 栈中的最小值
        minStack.push(Math.min(minStack.peek(),val));
    }

    public void pop() {
        stack.pop();
        //当前元素出栈时 最小值栈对应的位置也要出栈
        minStack.pop();
    }

    public int top() {
        return stack.peek();
    }

    public int getMin() {
        return minStack.peek();
    }

}


public class MinStackTest {

    public static void main(String[] args) {
        MinStack stack=new MinStack();
        stack.push(-3);
        stack.push(1);
        stack.push(23);
        System.out.println(stack.getMin());
    }

}

(3)有效的括号(20)

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

输入:s = "()"
输出:true

输入:s = "()[]{}"
输出:true

输入:s = "(]"
输出:false
public class Solution {

    public static void main(String[] args) {
        String s="()[]{}";
        Solution solution=new Solution();
        System.out.println(solution.isValid(s));
    }

    public boolean isValid(String s) {
        int n=s.length();
        //长度为奇数直接返回false
        if (n%2!=0){
            return false;
        }
        Stack<Character> stack=new Stack<>();
        Map<Character,Character> map=new HashMap<>();
        //将右括号和左括号分别以 key 和 value 存储
        map.put(')','(');
        map.put('}','{');
        map.put(']','[');
        //遍历字符串匹配括号
        for (int i=0;i<n;i++){
            char ch=s.charAt(i);
            if (map.containsKey(ch)){//如果ch是map集合里的key 也就是右括号
                //先判断stack是否为空或者栈顶元素是否与ch匹配
                if (stack.isEmpty()||stack.peek()!=map.get(ch)){
                    return false;
                }
                //如果匹配
                stack.pop();//弹出栈顶括号
            }else {//如果ch是左括号
                stack.push(ch);
            }
        }
        return stack.isEmpty();
    }
}

3.单调栈

(1)每日温度

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。

输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]

输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]

输入: temperatures = [30,60,90]
输出: [1,1,0]
public class Solution {

    public static void main(String[] args) {
        int[] arr={73,74,75,71,69,72,76,73};
        Solution solution=new Solution();
        int[] tem = solution.dailyTemperatures(arr);
        for (int i=0;i< tem.length;i++){
            System.out.print(tem[i]+" ");
        }
    }

    public int[] dailyTemperatures(int[] temperatures) {
        int n = temperatures.length;
        if (n==1){
            return new int[1];
        }
        int[] arr=new int[n];
        Stack<Integer> stack=new Stack<>();
        for (int i=0;i<n;i++){
            //当栈不为空并且栈顶温度小于当前温度时
            while (!stack.isEmpty()&&temperatures[i]>temperatures[stack.peek()]){
                arr[stack.peek()]=i-stack.pop();
            }
            //当上边两个条件不全满足时 将当前元素的下标入栈
            stack.push(i);
        }

        return arr;
    }
}

4.优先队列

(1)合并K个升序链表(23)

给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

输入:lists = []
输出:[]

输入:lists = [[]]
输出:[]
//顺序遍历合并每一个链表
public class Solution {

    public ListNode mergeKLists(ListNode[] lists) {
        ListNode list=null;//需要返回的链表
        //遍历每一个链表 然后与list合并
        for (int i=0;i< lists.length;i++){
            list=mergeTwoLists(lists[i],list);
        }
        return list;
    }

    private ListNode mergeTwoLists(ListNode a,ListNode b){
        if (a==null||b==null){
            return a!=null?a:b;
        }
        ListNode head=new ListNode(0);//设置一个头节点 返回的时候返回他的next节点
        ListNode tail=head;//记录下一个插入位置的前一个位置
        ListNode preA=a;//a链表的当前节点
        ListNode preB=b;//b链表的当前节点
        while (preA!=null&&preB!=null){
            if (preA.val<preB.val){
                tail.next=preA;
                preA=preA.next;
            }else {
                tail.next=preB;
                preB=preB.next;
            }
            tail=tail.next;
        }
        tail.next=preA!=null?preA:preB;
        return head.next;
    }
}


//采用分治合并
public class Solution {

    public ListNode mergeKLists(ListNode[] lists) {
        return merge(lists,0,lists.length-1);
    }

    private ListNode merge(ListNode[] lists,int left,int right){
        if (left==right){
            return lists[left];
        }
        if (left>right){
            return null;
        }
        int mid=(left+right)>>1;//因为lists.length<500 所以这里不用担心越界 可以使用left+right
        return mergeTwoLists(merge(lists, left, mid),merge(lists, mid+1, right));
    }

    private ListNode mergeTwoLists(ListNode a,ListNode b){
        if (a==null||b==null){
            return a!=null?a:b;
        }
        ListNode head=new ListNode(0);//设置一个头节点 返回的时候返回他的next节点
        ListNode tail=head;//记录下一个插入位置的前一个位置
        ListNode preA=a;//a链表的当前节点
        ListNode preB=b;//b链表的当前节点
        while (preA!=null&&preB!=null){
            if (preA.val<preB.val){
                tail.next=preA;
                preA=preA.next;
            }else {
                tail.next=preB;
                preB=preB.next;
            }
            tail=tail.next;
        }
        tail.next=preA!=null?preA:preB;
        return head.next;
    }
} 

5.双端队列

(1)滑动窗口最大值(239)

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

输入:nums = [1], k = 1
输出:[1]
//优先队列
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,3,-1,-3,5,3,6,7};
        int k=3;
        Solution solution=new Solution();
        int[] ints = solution.maxSlidingWindow(arr, k);
        for (int i:ints) {
            System.out.print(i+" ");
        }
    }

    public int[] maxSlidingWindow(int[] nums, int k) {
        int n= nums.length;
        int[] res=new int[n-k+1];
        //定义一个大根堆
        PriorityQueue<int[]> heap=new PriorityQueue<>(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if (o1[0]!=o2[0]){//如果元素值不相等 按照元素值降序排序
                    return o2[0]-o1[0];
                }
                //如果元素值相等 按照索引值降序排序
                return o2[1]-o1[1];
            }
        });
        //将数组前k个元素加入大根堆
        for (int i=0;i<k;i++){
            heap.add(new int[]{nums[i],i});
        }
        res[0]=heap.peek()[0];
        //开始滑动窗口
        for (int i=k;i<n;i++){
            heap.add(new int[]{nums[i],i});//当前元素加入大根堆
            //如果此时最大值不在窗口内 就将堆顶元素移除 直到堆顶元素最大值在当前窗口内
            //此时堆顶元素就是当前窗口内的最大值
            while (heap.peek()[1]<=i-k){
                heap.poll();//弹出堆顶元素
            }
            res[i-k+1]=heap.peek()[0];
        }
        return res;
    }
}

6.哈希表

哈希表又称为散列表,使用O(n)的空间复杂度存储数据,通过hash函数映射位置,从而实现近似O(1)的时间
复杂度的插入、删除、查找等操作

(1)两数之和(1)

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。

//暴力遍历
class Solution {

    public static void main(String[] args) {
        int[] arr={2,7,11,15};
        int k=9;
        Solution solution=new Solution();
        int[] ints = solution.twoSum(arr, k);
        for (int i:ints) {
            System.out.print(i+" ");
        }
    }
    
    public int[] twoSum(int[] nums, int target) {
        int n= nums.length;
        for (int i=0;i<n-1;i++){
            for (int j=i+1;j<n;j++){
                if (nums[j]==target-nums[i]){
                    return new int[]{i,j};
                }
            }
        }
        return new int[0];
    }
}


//使用hash表
public class Solution {

    public static void main(String[] args) {
        int[] arr={2,7,11,15};
        int k=9;
        Solution solution=new Solution();
        int[] ints = solution.twoSum(arr, k);
        for (int i:ints) {
            System.out.print(i+" ");
        }
    }

    public int[] twoSum(int[] nums, int target) {
        int n= nums.length;
        Map<Integer,Integer> map=new HashMap<>();
        for (int i=0;i<n;i++){
            //如果map里存在一个key使它和当前值相加等于target 直接返回他们的下标
            if (map.containsKey(target-nums[i])){
                return new int[]{map.get(target-nums[i]),i};
            }
            map.put(nums[i],i);
        }
        return new int[0];
    }
}

(2)最长连续序列(128)

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
public class Solution {

    public static void main(String[] args) {
        int[] arr={100,4,200,1,3,2};
        Solution solution=new Solution();
        System.out.println(solution.longestConsecutive(arr));
    }

    public int longestConsecutive(int[] nums) {
        int n= nums.length;
        if (n==0){
            return 0;
        } else if (n==1) {
            return 1;
        }
        Set<Integer> set=new HashSet<>();
        int longestLen=0;//最长序列长度
        //将数组中元素加入set集合中 并去重
        for (int i=0;i<n;i++){
            set.add(nums[i]);
        }
        //遍历数组中每一个元素
        for (int i=0;i<n;i++){
            //当一个元素在数组中不存在前驱元素时 从这个元素出发才可以得到当前最长序列
            //如果存在前驱元素 那么从前驱元素开始 得到的序列长度一定大于从当前这个元素开始的序列长度
            if (!set.contains(nums[i]-1)){
                int curLen=1;//当前长度
                int curNum=nums[i];//当前元素
                //当当前元素存在后继元素时 当前长度+1
                while (set.contains(curNum+1)){
                    curLen++;
                    curNum++;
                }
                longestLen=Math.max(longestLen,curLen);
            }
        }
        return longestLen;
    }
}

(3)直线上最多的点数

给你一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。

输入:points = [[1,1],[2,2],[3,3]]
输出:3
public class Solution {

    public static void main(String[] args) {
        int[][] arr={{1,1},{3,2},{5,3},{4,1},{2,3},{1,4}};
        Solution solution=new Solution();
        System.out.println(solution.maxPoints(arr));
    }

    public int maxPoints(int[][] points) {
        int n=points.length;
        if (n<=2){
            return n;
        }
        int maxPoint=0;//最多有多少个点在同一条直线上
        for (int i=0;i<n;i++){
            //当共线点的数量 > n/2时 或者 共线点的数量 >= 当前点i之后所剩的点的数量时 就直接退出循环
            if (maxPoint>=n-i||maxPoint>n/2){
                break;
            }
            //用map集合来存储每个不同直线上共线点的个数
            Map<Integer,Integer> map=new HashMap<>();
            for (int j=i+1;j<n;j++){
                int x=points[j][0]-points[i][0];
                int y=points[j][1]-points[i][1];
                //当x=0或者y=0时 将不为0的一方设置为1
                if (x==0){
                    y=1;
                } else if (y==0) {
                    x=1;
                }else {
                    //假设y始终为正数
                    if (y<0){
                        x=-x;
                        y=-y;
                    }
                    //求x和y的最大公倍数
                    int gcdXY=gcd(Math.abs(x),Math.abs(y));
                    //化简x和y
                    x/=gcdXY;
                    y/=gcdXY;
                }
                //将x和y用一个正数表示 作为集合的key
                int key=y+20001*x;
                if (map.containsKey(key)){//当集合中存在key时 点数+1
                    map.put(key,map.get(key)+1);
                }else {//集合中不存在key时 将这个key加入集合
                    map.put(key,1);
                }
            }
            int preMax=0;//当前i所在的最大点数
            //遍历当前的map集合 求出当前的最大值
            for (Map.Entry<Integer,Integer> entry: map.entrySet()){
                preMax=Math.max(preMax, entry.getValue()+1);
            }
            //将每一次的当前最大值与最大值做比较 求总的最大值
            maxPoint=Math.max(preMax,maxPoint);
        }
        return maxPoint;
    }

    private int gcd(int x,int y){
        return y!=0?gcd(y,x%y):x;
    }
}

7.前缀和与积分图

(1)区域和检索 - 数组不可变(303)

给定一个整数数组 nums,处理以下类型的多个查询:
计算索引 left 和 right (包含 left 和 right)之间的 nums 元素的 和 ,其中 left <= right
实现 NumArray 类:
NumArray(int[] nums) 使用数组 nums 初始化对象
int sumRange(int i, int j) 返回数组 nums 中索引 left 和 right 之间的元素的 总和 ,包含 left 和 right 两点(也就是 nums[left] + nums[left + 1] + … + nums[right] )

//暴力
public class NumArray {

    int[] arr;

    public NumArray(int[] nums) {
        this.arr=nums;
    }

    public int sumRange(int left, int right) {
        int sum=0;
        for (int i=left;i<=right;i++){
            sum+=arr[i];
        }
        return sum;
    }

}


//前缀和
public class NumArray {

    int[] arr;//前缀和数组

    public NumArray(int[] nums) {
        int n=nums.length;
        arr=new int[n+1];//前缀和数组的arr[0]=0 这样可以避免i=0的特殊判断
        for (int i=0;i<n;i++){
            arr[i+1]=arr[i]+nums[i];
        }
    }

    public int sumRange(int left, int right) {
        //left~right这个区间元素的和是 0~right的前缀和减去0~left-1的前缀和的值
        return arr[right+1]-arr[left];
    }

}

(2)二维区域和检索 - 矩阵不可变(304)

给定一个二维矩阵 matrix,以下类型的多个请求:
计算其子矩形范围内元素的总和,该子矩阵的 左上角 为 (row1, col1) ,右下角 为 (row2, col2) 。
实现 NumMatrix 类:
NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进行初始化
int sumRegion(int row1, int col1, int row2, int col2) 返回 左上角 (row1, col1) 、右下角 (row2, col2) 所描述的子矩阵的元素 总和 。

//使用一维前缀和
public class NumMatrix {

    int arr[][];

    public NumMatrix(int[][] matrix) {
        int m= matrix.length;//行
        int n=matrix[0].length;//列
        arr=new int[m][n+1];
        for (int i=0;i<m;i++){
            //计算出每一行的前缀和
            for (int j=0;j<n;j++){
                arr[i][j+1]=arr[i][j]+matrix[i][j];
            }
        }
    }

    public int sumRegion(int row1, int col1, int row2, int col2) {
        int sum=0;
        for (int i=row1;i<=row2;i++){
            sum+=arr[i][col2+1]-arr[i][col1];
        }
        return sum;
    }

}


//使用二维前缀和
public class NumMatrix {

    int arr[][];

    public NumMatrix(int[][] matrix) {
        int m= matrix.length;//行
        int n=matrix[0].length;//列
        arr=new int[m+1][n+1];
        //计算出第一行的所有列的前缀和
        for (int i=0;i<m;i++){
            for (int j=0;j<n;j++){
                arr[i+1][j+1]=arr[i][j+1]+arr[i+1][j]-arr[i][j]+matrix[i][j];
            }
        }
    }

    public int sumRegion(int row1, int col1, int row2, int col2) {
        return arr[row2+1][col2+1]-arr[row1][col2+1]-arr[row2+1][col1]+arr[row1][col1];
    }

}

(3)和为 K 的子数组(560)

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。

输入:nums = [1,1,1], k = 2
输出:2

输入:nums = [1,2,3], k = 3
输出:2
//暴力枚举
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,2,3};
        int k=3;
        Solution solution=new Solution();
        System.out.println(solution.subarraySum(arr,k));
    }

    public int subarraySum(int[] nums, int k) {
        int n= nums.length;
        int count=0;//连续子数组的个数
        //依次遍历每个元素 分别以每个元素结尾向前寻找 看能否找到连续子数组的和为k
        for (int i=0;i<n;i++){
            int sum=0;//连续子数组的和
            for (int j=i;j>=0;j--){
                sum+=nums[j];
                if (sum==k){
                    count++;
                }
            }
        }
        return count;
    }
}


//前缀和+哈希表优化
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,2,3};
        int k=3;
        Solution solution=new Solution();
        System.out.println(solution.subarraySum(arr,k));
    }

    public int subarraySum(int[] nums, int k) {
        int n= nums.length;
        int count=0;//连续子数组的个数
        int pre=0;//前缀和
        Map<Integer,Integer> map=new HashMap<>();
        map.put(pre,1);
        for (int i=0;i<n;i++){
            pre+=nums[i];
            if (map.containsKey(pre-k)){
                count+=map.get(pre-k);
            }
            map.put(pre,map.getOrDefault(pre,0)+1);
        }
        return count;
    }
}

8.练习

(1)重塑矩阵(566)

在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。

给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。

如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

输入:mat = [[1,2],[3,4]], r = 1, c = 4
输出:[[1,2,3,4]]

输入:mat = [[1,2],[3,4]], r = 2, c = 4
输出:[[1,2],[3,4]]
public class Solution {

    public static void main(String[] args) {
        int[][] arr={{1,2},{3,4}};
        int r=1;
        int c=4;
        Solution solution=new Solution();
        int[][] ints = solution.matrixReshape(arr, r, c);
        System.out.println("行:"+ints.length+"   "+"列:"+ints[0].length);
    }

    public int[][] matrixReshape(int[][] mat, int r, int c) {
        int m= mat.length;
        int n=mat[0].length;
        if (r*c!=m*n){
            return mat;
        }
        int[][] arr=new int[r][c];
        Queue<Integer> queue=new LinkedList<>();
        //将数组元素入队列
        for (int i=0;i<m;i++){
            for (int j=0;j<n;j++){
                queue.add(mat[i][j]);
            }
        }
        //将队列的元素插入新的数组
        for (int i=0;i<r;i++){
            for (int j=0;j<c;j++){
                arr[i][j]=queue.poll();
            }
        }
        return arr;
    }
}

(2)用队列实现栈(225)

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

public class MyStack {

    Queue<Integer> queue;
    Queue<Integer> auxQueue;//辅助栈

    public MyStack() {
        queue=new LinkedList<>();
        auxQueue=new LinkedList<>();
    }

    public void push(int x) {
        //首先将queue里剩余的元素弹入auxQueue中 为了保证元素顺序
        while (!queue.isEmpty()){
            auxQueue.add(queue.poll());
        }
        //将auxQueue中元素按照顺序弹入queue中
        while (!auxQueue.isEmpty()){
            queue.add(auxQueue.poll());
        }
        queue.add(x);
    }

    public int pop() {
        //首先将queue里剩余的元素弹入auxQueue中 为了保证元素顺序
        while (!queue.isEmpty()){
            auxQueue.add(queue.poll());
        }
        //在每一次操作前 先将auxQueue中的元素弹入queue中
        while (!auxQueue.isEmpty()){
            queue.add(auxQueue.poll());
        }
        while (queue.size()>1){
            auxQueue.add(queue.poll());
        }
        return queue.poll();
    }

    public int top() {
        //首先将queue里剩余的元素弹入auxQueue中 为了保证元素顺序
        while (!queue.isEmpty()){
            auxQueue.add(queue.poll());
        }
        //在每一次操作前 先将auxQueue中的元素弹入queue中
        while (!auxQueue.isEmpty()){
            queue.add(auxQueue.poll());
        }
        while (queue.size()>1){
            auxQueue.add(queue.poll());
        }
        return queue.peek();
    }

    public boolean empty() {
        while (queue.isEmpty()&&auxQueue.isEmpty()){
            return true;
        }
        return false;
    }
}

(3)下一个更大元素 II(503)

给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。

数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。

输入: nums = [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

输入: nums = [1,2,3,4,3]
输出: [2,3,4,-1,4]
//小根堆+循环数组
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,2,1};
        Solution solution=new Solution();
        int[] ints = solution.nextGreaterElements(arr);
        for (int i:ints){
            System.out.print(i+" ");
        }
    }

    public int[] nextGreaterElements(int[] nums) {
        int n= nums.length;
        if (n==1){
            return new int[]{-1};
        }
        int[] arr=new int[n];
        //先将数组中所有位置初始化为-1
        Arrays.fill(arr,-1);
        PriorityQueue<int[]> heap=new PriorityQueue<>(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if (o1[0]==o2[0]){
                    return o1[1]-o2[1];
                }
                return o1[0]-o2[0];
            }
        });
        for (int i=0;i<n*2-1;i++){
            //当小根堆不为空并且堆顶元素小于当前元素时 堆顶元素对应位置放当前元素
            while (!heap.isEmpty()&&heap.peek()[0]<nums[i%n]){
                arr[heap.poll()[1]]=nums[i%n];
            }
            //当前元素入堆
            heap.add(new int[]{nums[i%n],i%n});
        }
        return arr;
    }
}


//单调栈+循环数组
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,2,1};
        Solution solution=new Solution();
        int[] ints = solution.nextGreaterElements(arr);
        for (int i:ints){
            System.out.print(i+" ");
        }
    }

    public int[] nextGreaterElements(int[] nums) {
        int n= nums.length;
        if (n==1){
            return new int[]{-1};
        }
        int[] arr=new int[n];
        //先将数组中所有位置初始化为-1
        Arrays.fill(arr,-1);
        //单调栈中保存数组元素下标
        Deque<Integer> stack=new LinkedList<>();
        for (int i=0;i<n*2-1;i++){
            //当栈不为空并且当前元素大于栈顶下标所对应的元素时 将栈顶元素对应位置赋值为当前元素
            while (!stack.isEmpty()&&nums[stack.peek()]<nums[i%n]){
                arr[stack.poll()]=nums[i%n];
            }
            //当前元素下标入栈
            stack.push(i%n);
        }
        return arr;
    }
}

(4)存在重复元素(217)

给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

输入:nums = [1,2,3,1]
输出:true

输入:nums = [1,2,3,4]
输出:false

输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true
//排序
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,2,1};
        Solution solution=new Solution();
        System.out.println(solution.containsDuplicate(arr));
    }

    public boolean containsDuplicate(int[] nums) {
        int n=nums.length;
        if (n==1){
            return false;
        }
        Arrays.sort(nums);
        for (int i=0;i<n-1;i++){
            if (nums[i]==nums[i+1]){
                return true;
            }
        }
        return false;
    }
}


//集合
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,2,1};
        Solution solution=new Solution();
        System.out.println(solution.containsDuplicate(arr));
    }

    public boolean containsDuplicate(int[] nums) {
        int n=nums.length;
        if (n==1){
            return false;
        }
        Set<Integer> set=new HashSet<>();
        for (int i=0;i<n;i++){
            //当集合中存在某个值时 证明这个值算上当前值至少出现了两次 直接返回true
            if (set.contains(nums[i])){
                return true;
            }
            set.add(nums[i]);
        }
        return false;
    }
}

(5)数组的度

给定一个非空且只包含非负数的整数数组 nums,数组的 度 的定义是指数组里任一元素出现频数的最大值。

你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。

输入:nums = [1,2,2,3,1]
输出:2
解释:
输入数组的度是 2 ,因为元素 1 和 2 的出现频数最大,均为 2 。
连续子数组里面拥有相同度的有如下所示:
[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
最短连续子数组 [2, 2] 的长度为 2 ,所以返回 2 。

输入:nums = [1,2,2,3,1,4,2]
输出:6
解释:
数组的度是 3 ,因为元素 2 重复出现 3 次。
所以 [2,2,3,1,4,2] 是最短子数组,因此返回 6 。
//哈希表
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,2,2,3,1};
        Solution solution=new Solution();
        System.out.println(solution.findShortestSubArray(arr));
    }

    public int findShortestSubArray(int[] nums) {
        int n= nums.length;
        if (n==1){
            return 1;
        }
        int maxCount=0;//出现最大的频数
        int minLen=0;//出现频数最多且子数组长度最短的长度
        //哈希表 用来存储元素 和 其出现的次数以及第一次出现和最后一次出现的位置
        Map<Integer,int[]> map=new HashMap<>();
        for (int i=0;i<n;i++){
            if (map.containsKey(nums[i])){
                //更新出现的次数已经最后一次出现的位置
                map.get(nums[i])[0]++;
                map.get(nums[i])[2]=i;
            }else {
                map.put(nums[i],new int[]{1,i,i});
            }
        }
        //依次获取每一个value 比较它们的次数以及对应的子数组的长度 得到答案
        for (Map.Entry<Integer,int[]> entry:map.entrySet()){
            int[] arr= entry.getValue();
            if (maxCount<arr[0]){
                maxCount=arr[0];//令maxCount=当前频数
                minLen=arr[2]-arr[1]+1;//更改当前最短子数组长度
            } else if (maxCount==arr[0]) {
                minLen=Math.min(minLen,arr[2]-arr[1]+1);
            }
        }
        return minLen;
    }
}

(6)最长和谐子序列(594)

和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。

现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。

数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。

输入:nums = [1,3,2,2,5,2,3,7]
输出:5
解释:最长的和谐子序列是 [3,2,2,2,3]

输入:nums = [1,2,3,4]
输出:2

输入:nums = [1,1,1,1]
输出:0
//排序
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,2,3,4};
        Solution solution=new Solution();
        System.out.println(solution.findLHS(arr));
    }

    public int findLHS(int[] nums) {
        int n= nums.length;
        if (n<2){
            return 0;
        }
        int maxLen=0;//最长和谐子序列的长度
        Arrays.sort(nums);
        for (int i=0;i<n-1;i++){
            int j=i;
            int preMin=nums[i];//当前和谐子序列最小值
            //当当前子序列满足和谐子序列时
            while (j<(n-1)&&(preMin+1)>=nums[j+1]){
                j++;
            }
            //当当前最小值不等于最大值时 才成立
            if (preMin!=nums[j]){
                maxLen=Math.max(maxLen,j-i+1);
            }
        }
        return maxLen;
    }

}


//哈希表
public class Solution {

    public static void main(String[] args) {
        int[] arr={1,2,3,4};
        Solution solution=new Solution();
        System.out.println(solution.findLHS(arr));
    }

    public int findLHS(int[] nums) {
        int n= nums.length;
        if (n<2){
            return 0;
        }
        int maxLen=0;//最长和谐子序列的长度
        Map<Integer,Integer> map=new HashMap<>();
        //遍历数组 得到每个元素出现的次数
        for (int i=0;i<n;i++){
            if (map.containsKey(nums[i])){
                map.put(nums[i],map.get(nums[i])+1);
            }else {
                map.put(nums[i],1);
            }
        }
        //遍历map 对每一个key值 如果找到key+1也在map里 那么它们对应的和谐子序列长度就是它们的value值相加
        for (int key:map.keySet()){
            if (map.containsKey(key+1)){
                maxLen=Math.max(maxLen,map.get(key)+map.get(key+1));
            }
        }
        return maxLen;
    }

}

(7)寻找重复数(287)

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

输入:nums = [1,3,4,2,2]
输出:2

输入:nums = [3,1,3,4,2]
输出:3
public class Solution {

    public static void main(String[] args) {
        int[] arr={3,1,3,4,2};
        Solution solution=new Solution();
        System.out.println(solution.findDuplicate(arr));
    }

    public int findDuplicate(int[] nums) {
        int n= nums.length;
        int repeatNum=0;//重复的整数
        int left=1;
        int right=n-1;
        while (left<=right){
            int mid=(left+right)>>1;
            int count=0;//计数 来判断重复的数出现在哪
            for (int i=0;i<n;i++){
                if (nums[i]<=mid){
                    count++;
                }
            }
            if (count<=mid){
                left=mid+1;
            }else {
                right=mid-1;
                repeatNum=mid;
            }
        }
        return repeatNum;
    }

}

(8)优势洗牌(870)

给定两个大小相等的数组 nums1 和 nums2,nums1 相对于 nums2 的优势可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描述。
返回 nums1 的任意排列,使其相对于 nums2 的优势最大化。

输入:nums1 = [2,7,11,15], nums2 = [1,10,4,11]
输出:[2,11,7,15]

输入:nums1 = [12,24,8,32], nums2 = [13,25,32,11]
输出:[24,32,8,12]
    public int[] advantageCount(int[] nums1, int[] nums2) {
        int n= nums1.length;
        int[] arr=new int[n];
        Integer[] a=new Integer[n];
        Integer[] b=new Integer[n];
        int left=0;//数组当前左边界
        int right=n-1;//数组当前有边界
        for (int i=0;i<n;i++){
            a[i]=i;
            b[i]=i;
        }
        //a b 分别来存储 nums1 nums2 排序后的下标值
        Arrays.sort(a,(i,j)->nums1[i]-nums1[j]);
        Arrays.sort(b,(i,j)->nums2[i]-nums2[j]);
        for (int i=0;i<n;i++){
            //当nums1的当前最小值大于nums2的当前最小值时
            if (nums1[a[i]]>nums2[b[left]]){
                arr[b[left]]=nums1[a[i]];
                left++;
            }else {
                arr[b[right]]=nums1[a[i]];
                right--;
            }
        }
        return arr;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/165952.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

“链引擎”(PBC)计划 | 太保集团长安链应用展示

引言 长安链“链引擎”计划&#xff08;Powered by Chainmaker&#xff09;(简称&#xff1a;PBC计划)是由长安链生态联盟发起的一项应用赋能计划&#xff0c;旨在以长安链技术体系为核心支撑&#xff0c;汇聚产业各方力量&#xff0c;为应用方提供技术、品牌、生态等支持&…

面试干货!初级软件测试面试题及答案题库一起奉上

软件测试工程师面试通常要经历技术面以及HR面&#xff0c;HR面一般都是日常问题&#xff0c;面试人可以临场发挥过去&#xff0c;但关乎岗位职责的技术面&#xff0c;可就没那么容易了&#xff0c;尤其是对于很多初次去面试测试岗位的没有任何测试岗位面试经验的转行人员&#…

Java并发面试题

基础知识 并发编程的优缺点 为什么要使用并发编程&#xff08;并发编程的优点&#xff09; 充分利用多核CPU的计算能力&#xff1a;通过并发编程的形式可以将多核CPU的计算能力发挥到极致&#xff0c;性能得到提升方便进行业务拆分&#xff0c;提升系统并发能力和性能&#…

【网络安全】内网介绍+windows信息收集(含命令)

目录 前言 一、内网渗透测试是什么&#xff1f; 1.介绍 2.内外网区别 3.工作组是什么&#xff1f; 4.域是什么&#xff1f; 5.域的知识点 6.活动目录 7.活动目录主要功能 8.域权限 二、windows信息收集 &#xff08;1&#xff09;系统信息 &#xff08;2&#xff0…

【pandas】17 数据处理和绘图

【pandas】17 数据处理和绘图 2023.1.16 pandas数据处理方法和绘图&#xff1a;读取数据、更改数据、时间数据等 主要参考&#xff1a;https://mofanpy.com/tutorials/data-manipulation/pandas/time 17.1运算方法 17.1.1 筛选赋值运算 就是用前面的方法对数据进行筛选&#…

AI中Deepfake的部分研究前沿与文献综述

AI中Deepfake的部分研究前沿与文献综述一、研究现状二、典型算法&#xff1a;三、存在问题四、未来的研究热点参考文献&#xff1a;一、研究现状 由于Deepfake其潜在的安全威胁&#xff0c;它已经引起了学术界和工业界的研究兴趣。为了减轻这种风险&#xff0c;人们提出了许多…

【Nginx01】Ngnix入门

1.版本 Nginx开源版Nginx plus商业版OpenrestyTengine 2.Nginx开源版安装 2.1下载 2.2编译安装 如果本身没有c语言的编译器 命令&#xff1a; yum install -y gcc 解压Nginx 命令&#xff1a; tar -zxvf nginx-1.22.1.tar.gz 安装perl库 命令&#xff1a; yum install -y p…

广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署”

文章目录广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署”服务 Docker 构建及部署代码支持服务打包&构建服务部署广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署” 服务 Docker 构建及部署 在 ADX 系统中&#xff0c;全链路涉及 大大小小的微服务…

SpringBoot+VUE前后端分离项目学习笔记 - 【22 权限菜单 下】

本节主要实现用户角色菜单分配功能&#xff0c;并且实现前端的动态渲染以及动态路由 数据库&#xff1a; sys_user表增加role字段; sys_role增加flag字段;sys_menu表增加page_path字段。前两者表示用户角色标识&#xff0c;后者是前端页面vue路径&#xff0c;用以实现动态路由 …

verilog学习笔记- 13)呼吸灯实验

目录 简介&#xff1a; 实验任务&#xff1a; 硬件设计&#xff1a; 程序设计&#xff1a; 下载验证&#xff1a; 简介&#xff1a; 呼吸灯采用 PWM 的方式&#xff0c;在固定的频率下&#xff0c;通过调整占空比的方式来控制 LED 灯亮度的变化。PWM即脉冲宽度调制&#x…

2021年帆软杯一等奖作品 |《基于数据可视化的中国编程岗位需求分析》

# 作品主题 #——基于数据可视化的中国编程岗位需求分析一、团队介绍 团队名称&#xff1a;汪汪队立大功 团队成员&#xff1a;乔好鑫、许春阳、窦晨辉 指导老师&#xff1a;施金妹 团队的三位成员均是来自于海南科技职业大学大数据技术与应用专业&#xff0c;专业课主修了pyt…

SpringBoot+2次MD5登录密码加密+MyBatisPlus+Thymeleaf+Bootstrap简单实现登录功能,一文轻松搞定!

这里写目录标题一、演示GIF二、开发前期准备1、数据库2、依赖POM.XML3、idea结构目录三、后端1、实体类2、mapper接口3、mapper.xml4、Servicce接口5、Impl实现6、Controller控制器7、全局异常处理类GlobalExceptionGlobalExceptionHandler8、工具类MD5UtilUUIDUtilCookieUtilV…

消息批处理端口说明

为满足用户需要对多文件做批处理的需求&#xff0c;在2022版本的知行之桥中&#xff0c;开发人员开发设计了3个新的端口&#xff0c;分别是Batch Create 端口、Batch Merge 端口和Batch Split 端口。 功能是对传入端口的消息做批处理&#xff0c;使得消息可以在批处理组中分组在…

mybatis-plus分布式id重复问题

问题起因 k8s 部署的一个服务的两个节点集群 最近频繁报错&#xff0c;数据库主键ID重复&#xff0c;导致数据插入报错 问题定位 还在定位。。。。 问题解决 解决办法主要有两个 指定mybatis-plus workerId dataCenterId 全局配置 #注意这里使用的随机策略 随机区间 …

智能边缘网关

背景介绍 调研发现&#xff0c;数字经济为工业物联网、智能交通以及智慧医疗等场景提出了新的解决方案。工程师利用传感器边缘网关云服务器的系统架构&#xff0c;通过大数据及人工智能算法进行辅助决策&#xff0c;最终为工业设备赋能&#xff0c;提高加工生产效率。近年来&am…

sqli-labs 11~14 多命通关攻略(报错注入)

sqli-labs 11~14 多命通关攻略&#xff08;报错注入&#xff09;描述判断注入类型返回结果错误输入总结符号注释判断返回结果中的列数判断返回结果中的列数为 1判断返回结果中的列数为 2报错注入通过报错注入爆破数据库中的表名通过报错注入爆破数据库中的表名&#xff08;逻辑…

【高阶数据结构】封装unordered_map 和 unordered_set

&#x1f308;欢迎来到数据结构专栏~~封装unordered_map 和 unordered_set (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&…

【北京理工大学-Python 数据分析-3.1Pandas库的基本使用】

Pandas库的引用&#xff0c;常用两大功能Series(一维&#xff09;和DataFrame&#xff08;二维和多维&#xff09; Pandas是Python第三方库&#xff0c;提供高性能易用数据类型的分析工具。 Pandas基于NumPy实现&#xff0c;常与NumPy和Matplotlib一起使用。 Numpy和Pandas的…

SpringCloud-Netflix学习笔记03——什么是Eureka

什么是Eureka Eureka&#xff1a;怎么读&#xff1f; Netflix 在设计Eureka 时&#xff0c;遵循的就是AP原则。 1、CAP原则又称CAP定理&#xff0c;指的是在一个分布式系统中 2、一致性&#xff08;Consistency&#xff09; 3、可用性&#xff08;Availability&#xff09; 4、…

详细实例说明+典型案例实现 对动态规划法进行全面分析 | C++

第三章 动态规划法 目录 ●第三章 动态规划法 ●前言 ●一、动态规划法是什么&#xff1f; 1.简要介绍 2.生活实例 ●二、动态规划法对斐波那契数列的优化 1.优化方法 2.优化核心代码片段 3.代码实现以及结果展示 ●三、动态规划法的典型案例——最短总距离 …