代码随想录刷题日志

105 阅读5分钟

数组

二分查找

package 数组;

/**
 * @author zwf
 * @Package: 数组
 * @ClassName: 二分查找
 * @Description:
 * @date 2023/4/13 13:58
 * 输入: nums = [-1,0,3,5,9,12], target = 9
 * 输出: 4
 * 解释: 9 出现在 nums 中并且下标为 4
 */
public class 二分查找 {
    public static void main(String[] arg){
        int[] arr={-1,0,3,5,9,12};
        int target=9;
        System.out.println(search(arr, 9));
        System.out.println(search1(arr, 9));
    }
    //二分查找
    public static int search(int[] nums, int target) {
        int len=nums.length;
        int left=0;
        int right=len-1;
        //判断条件 left<=right 左闭右闭
        while (left<=right){
            int med=(left+right)>>1;
            if (target<nums[med]){
                right=med-1;
            }else if (target>nums[med]){
                left=med+1;
            }else if (target==nums[med]){
                return med;
            }
        }
        return -1;
    }
    //左闭右开
    public static int search2(int[] nums,int target){
        //获取数组元素个数
        int len=nums.length;
        //左右指针
        int left=0;int right=len-1;
        //判断条件 left<right 左闭右开
        while (left<right){
            //获取中间索引 (left+right)/2=>left/2+right/2=> left-left/2+right/2 防止int越界
            int medIndex=left-((left-right)>>1); //这里括号记得加上,加号优先级大于右移运算符
            if (nums[medIndex]<target){//目标值比中间值大,left指针右移到中间值后一位
                left=medIndex+1;
            }else if (nums[medIndex]<target) {//目标值比中间值小,right指针左移到中间值(因为右边是开区间)
                right = medIndex;
            }if(nums[medIndex]==target){
                return medIndex;
            }
        }
        return -1;
    }

    //优化递归实现
    public static int search1(int[] nums,int target){
        int l=0,r=nums.length-1;
        return dichotomy(nums,target,l,r);
    }
    public static int dichotomy(int[] nums,int target ,int l,int r){
        int medindex=l+(r-l)/2;// l+r/2-l/2
        if (l>r){
            return -1;
        }
        if (nums[medindex]>target)
            //向左边递归查找
            return dichotomy(nums,target,l,medindex-1);
        else if (nums[medindex]<target)
            //向右边递归查找
            return dichotomy(nums,target,medindex+1,r);
        else
            return medindex;
    }
}

移除元素

package 数组;

import java.util.Arrays;

/**
 * @author zwf
 * @Package: 数组
 * @ClassName: 移除元素
 * @Description:
 * @date 2023/4/13 14:46
 * 示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2,
 * 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
 */
public class 移除元素 {
    public static void main(String[] args) {
        int[] nums = {3, 2, 2, 3};
        int var=2;
        System.out.println(remove2(nums, 2));
        System.out.println(Arrays.toString(nums));
    }

    /**
     * @param arr 数组
     * @param val 要移除的元素
     * @return
     */
    public static int remove(int[] arr, int val) {
        //定义快慢指针
        int show = 0, fast = 0;
        //循环条件:快指针走完循环结束
        while (fast < arr.length) {
            //如果快指针不等于要删除的元素,移动快慢指针
            if (arr[fast] != val) {
                arr[show] = arr[fast];
                //让慢指针跟在快指针后面
                show++;
            }
            fast++;
        }
        return show;
    }
    //比较好理解但是思路是一样的
    public static int remove1(int[] arr,int val){
        //定义快慢指针
        int show = 0, fast = 0;
        //快指针遍历完循环结束
        while (fast<arr.length){
            //快指针找到要删除元素就进行向前走一位慢指针不动,依就指向要插入位置
            if (arr[fast]==val){
                fast++;
            }else if (arr[fast]!=val){ //插入覆盖要删除元素
                arr[show++]=arr[fast++];
            }
        }
        return show;
    }
    //所有for循环思路相同
    public static int remove2(int[] arr,int val){
        int show = 0;
        for (int fast=0;fast<arr.length;fast++){
            if(arr[fast]!=val){
                arr[show++]=arr[fast];
            }
        }
        return show;
    }
}

image-20221117193005540转存失败,建议直接上传图片文件

有序数组的平方

package day07;

import java.util.Arrays;

/**
 * @author zwf
 * @Package: day07
 * @ClassName: 有序数组的平方
 * @Description:
 * @date 2022/11/18 9:21
 * 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
 *
 * 示例 1: 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
 *
 * 示例 2: 输入:nums = [-7,-3,2,3,11] 输出:[4,9,9,49,121]
 */
public class 有序数组的平方 {
    public static void main(String[] args) {
        int[] nums = {-4, -1, 0, 3, 10};
        System.out.println(Arrays.toString(square(nums)));
        System.out.println(Arrays.toString(square1(nums)));
    }

    public static int[] square(int[] arr) {
        int[] result = new int[arr.length];
        int left = 0;
        int right = arr.length - 1;
        int index = arr.length - 1;
        while (left <= right) {
            if (arr[left] * arr[left] > arr[right] * arr[right]) {
                result[index--] = arr[left] * arr[left];
                left++;
            } else {
                result[index--] = arr[right] * arr[right];
                --right;
            }
        }
        return result;
    }

    public static int[] sortedSquares(int[] arr){
        int index=arr.length-1;
        int[] nums = new int[arr.length];
        for (int l = 0,r=arr.length-1; l <= r; l++,r--) {
            int x=arr[l]*arr[l];
            int y=arr[r]*arr[r];
            if (x>y){
                nums[index--]=x;
                r++;
            }else {
                nums[index--]=y;
                l--;
            }
        }
        return nums;
    }
}

长度最小的子数组

package 数组;

/**
 * @author zwf
 * @Package: 数组
 * @ClassName: 长度最小的子数组
 * @Description:
 * @date 2023/4/13 15:13
 * 输入:s = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
 */
public class 长度最小的子数组 {
    public static void main(String[] args) {
        int[] nums = {4, 0, 0, 3, 2};
        System.out.println(minSubArrayLen(nums.length,nums));
        System.out.println(minSubArrayLen1(nums.length,nums));
    }
    /**
     * @param s 指定值
     * @param nums 数组
     * @return
     */
    public  static int minSubArrayLen1(int s,int[] nums){
        int left=0;
        int sum=0;
        int result=Integer.MAX_VALUE;
        for (int right=0;right<nums.length;right++){
            sum+=nums[right];//累加
            while (sum>=s){//当累加结果大于s时,从左指针中去数值在判断
                //取两数编号之间的个数 如:编号0-1两个箱子 所以为(1-0)+1=2个
                result=Math.min(result,right-left+1);
                sum=sum-nums[left++];
            }
        }
        return result==Integer.MAX_VALUE?0:result; //result始终取最小值
    }

    /**
     * @param s
     * @param nums
     * @return 思路相同就是这样时间复杂度高 属于暴力解法
     */
    public static int minSubArrayLen(int s,int[] nums){
        int n=nums.length;
        if (n==0){
            return 0;
        }
        int ans=Integer.MAX_VALUE;
        for (int i=0;i<n;i++){ //遍历
            int sum=0;
            for (int j=i;j<n;j++){
                sum+=nums[j];
                if (sum>=s){
                    ans=Math.min(ans,j-i+1);
                    break;
                }
            }
        }
        return ans==Integer.MAX_VALUE?0:ans;
    }
}

螺旋矩阵

package day07;

import java.util.ArrayList;

/**
 * @author zwf
 * @Package: day07
 * @ClassName: 螺旋矩阵
 * @Description:
 * @date 2022/11/18 17:06
 */
public class 螺旋矩阵 {
    public static void main(String[] args) {
        int[][] ints = generateMatrix1(3);
        for (int i = 0; i < ints.length; i++) {
            for (int j=0;j<ints[i].length;j++){
                System.out.format("%4s",ints[i][j]);
            }
            System.out.println();
        }
    }

    public static int[][] generateMatrix(int n) {
        int loop=0;
        int[][] res=new int[n][n];
        int start=0;
        int count=1;
        int i,j;
        while (loop++<n/2){
            //模拟上侧从左到右
            for (j=start;j<n-loop;j++){
                res[start][j]=count++;
            }
            //模拟右侧从上到下
            for (i=start;i<n-loop;i++){
                res[i][j]=count++;
            }
            //模拟下侧从右到左
            for (;j>=loop;j--){
                res[i][j]=count++;
            }
            //模拟左侧从下到上
            for (;i>=loop;i--){
                res[i][j]=count++;
            }
            start++;
        }
        if (n%2==1){
            res[start][start]=count;
        }
        return res;
    }
    public  static int[][] generateMatrix1(int n) {
        int maxNum = n * n;
        int curNum = 1;
        int[][] matrix = new int[n][n];
        int row = 0, column = 0;
        int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 右下左上
        int directionIndex = 0;
        while (curNum <= maxNum) {
            matrix[row][column] = curNum;
            curNum++;
            int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1];
            if (nextRow < 0 || nextRow >= n || nextColumn < 0 || nextColumn >= n || matrix[nextRow][nextColumn] != 0) {
                directionIndex = (directionIndex + 1) % 4; // 顺时针旋转至下一个方向
            }
            row = row + directions[directionIndex][0];
            column = column + directions[directionIndex][1];
        }
        return matrix;
    }
    public  static int[][] generateMatrix2(int n) {
       int l=0,r=n-1,t=0,b=n-1;
       int [][] mat=new int[n][n];
       int num=1,tar=n*n;
       while (num<=tar){
           //从左到右
           for (int i=l;i<=r;i++){
               mat[t][i]=num++;
           }
           t++;
           //从上到下
           for (int i=t;i<=b;i++){
               mat[i][r]=num++;
           }
           r--;
           //从右到左
           for (int i=r;i>=l;i--){
               mat[b][i]=num++;
           }
           b--;
           //从下到上
           for (int i=b;i>=t;i--){
               mat[i][l]=num++;
           }
           l++;
       }
       return mat;
    }
}

链表

单向链表

package LinkedList;

/**
 * @author zwf
 * @Package: LinkedList
 * @ClassName: ListNode
 * @Description:
 * @date 2022/11/29 13:44
 */
public class ListNode {
    // 结点的值
    int val;

    // 下一个结点
    ListNode next;

    // 节点的构造函数(无参)
    public ListNode() {
    }

    // 节点的构造函数(有一个参数)
    public ListNode(int val) {
        this.val = val;
    }

    // 节点的构造函数(有两个参数)
    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

移除链表元素

package linkedlist;

import util.Node;

/**
 * @author zwf
 * @Package: linkedlist
 * @ClassName: 移除链表元素
 * @Description:
 * @date 2023/2/22 14:44
 */
public class 移除链表元素 {
    public  class ListNode {
        int val;
        ListNode next;
        ListNode() {}
        ListNode(int val) { this.val = val; }
        ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    }
    
    public ListNode removeElements(ListNode head, int val) {
        //删除值相同的头结点后,可能新的头结点也值相等,用循环解决
        while (head!=null&&head.val==val){
            head=head.next;
        }
        if (head==null){
            return head;
        }
        ListNode prev=head;
        while (prev.next!=null){
            if (prev.next.val==val){
                prev.next=prev.next.next;
            }else {
                prev=prev.next;
            }
        }
        return head;
    }
    //虚拟头结点
    public ListNode removeElements1(ListNode head, int val) {
        //创建一个虚拟头结点
        ListNode dummyNode=new ListNode(0);
        dummyNode.next=head;
        ListNode prev=dummyNode;
        while (prev.next!=null){
            if (prev.next.val==val){
                prev.next=prev.next.next;
            }else {
                prev=prev.next;
            }
        }
        return dummyNode.next;
    }
    //递归
    public ListNode removeElements2(ListNode head, int val) {
       if (head==null){
           return null;
       }
       head.next=removeElements2(head.next,val);
       if (head.val==val){
           return head.next;
       }else {
           return head;
       }
    }
}

设计链表

package linkedlist;

import util.ListNode;

/**
 * @author zwf
 * @Package: linkedlist
 * @ClassName: MyLinkedLIst
 * @Description:
 * @date 2023/2/22 15:42
 */
public class MyLinkedList {
    ListNode head;//头节点
    int size;
    /**
     * get(index):获取链表中第index个节点的值。如果索引无效,则返回-1;
     * addAtHead(val):在链表的第一个元素之前添加一个值为val的节点。插入后,新节点将成为链表的第一个节点。
     * addAtTail(val):将值为val的节点追加到链表的最后一个元素
     * addAtIndex(index,val):在链表中的第index个节点之前添加值为val的节点。
     * deleteAtIndex(index):如果索引index有效,则1删除链表中的第index个节点
     */
    public MyLinkedList() {
        head=new ListNode(0);
        size=0;
    }
    public int get(int index) {
        if (index<0&&index>=size){
            throw new RuntimeException("index不合法");
        }
        ListNode temp=head;
        for (int i=0;i<=index;i++){
            temp=temp.next;
        }
        return temp.val;
    }
    //添加到链表头部
    public void addAtHead(int val) {
        addAtIndex(0,val);
    }
    //添加到链表尾部
    public void addAtTail(int val) {
        addAtIndex(size,val);
    }
    //返回头
    public ListNode getHead() {
        return head.next;
    }

    public void addAtIndex(int index, int val) {
        if (index>size){
            return;
        }
        index=Math.max(0,index);
        size++;
        ListNode temp=head;
        for (int i=0;i<index;i++){
            temp=temp.next;
        }
        ListNode toAdd = new ListNode(val);
        toAdd.next=temp.next;
        temp.next=toAdd;
    }
    //删除
    public void deleteAtIndex(int index) {
        if (index<0||index>=size){
            return;
        }
        size--;
        ListNode temp=head;
        //找到要删除元素的前一个元素
        for (int i=0;i<index-1;i++){
            temp=temp.next;
        }
        temp.next=temp.next.next;
    }
    //遍历链表
    public void list(){
        ListNode temp=head;
        while (temp.next!=null){
            System.out.print(temp.next.val+"=>");
            temp=temp.next;
        }
    }

}

反转链表

package linkedlist;

import util.ListNode;

import java.util.Stack;

/**
 * @author zwf
 * @Package: linkedlist
 * @ClassName: reverseList
 * @Description:
 * @date 2023/2/22 19:04
 */
public class reverseList {
    //反转链表
    public ListNode reverseList(ListNode head) {
        if (head==null||head.next==null){
            return head;
        }
        ListNode newHerd=reverseList(head.next);
        head.next.next=head;
        head.next=null;
        return newHerd;
    }
    public ListNode reverseList1(ListNode head) {
        ListNode cur=head; //后指针
        ListNode front=null;//前指针
        ListNode next=null;//保存下一个节点
        while (cur!=null) {
            next = cur.next;
            cur.next = front;
            front = cur;
            cur = next;
        }
        return front;
    }
    //使用栈解决反转链表的问题
    public ListNode reverseList2(ListNode head) {
       //如果链表为空,或者只有一个元素直接返回
        if (head==null||head.next==null)return head;
        //创建栈 每一个节点都入栈
        Stack<ListNode> stack = new Stack<>();
        ListNode cur=head;
        while (cur!=null){
            stack.push(cur);
            cur=cur.next;
        }
        //创建一个虚拟头节点
        ListNode pHead=new ListNode(0);
        cur=pHead;
        while (!stack.isEmpty()){
            ListNode node=stack.pop();
            cur.next=node;
            cur=cur.next;
        }
        //最后一个元素的next赋空值
        cur.next=null;
        return pHead.next;
    }

}

两两交换链表中的节点

package linkedlist;

import util.ListNode;

/**
 * @author zwf
 * @Package: linkedlist
 * @ClassName: liko24
 * @Description: 两两交换链表中的节点
 * @date 2023/2/23 18:59
 */
public class liko24 {
    /**
     * 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
     */
    public ListNode swapPairs(ListNode head) {
        ListNode temp=new ListNode(0);//虚拟头节点
        temp.next=head;
        ListNode cur=temp;
        while (cur.next!=null&&cur.next.next!=null){
            ListNode listNode=cur.next;
            ListNode listNode1=cur.next.next.next;
            cur.next=cur.next.next;
            cur.next.next=listNode;
            listNode.next=listNode1;
            //后移两位
            cur=cur.next.next;
        }
        return temp.next;
    }
}

删除链表的倒数第N个节点

package linkedlist;

import util.ListNode;

/**
 * @author zwf
 * @Package: linkedlist
 * @ClassName: liko19
 * @Description: 删除链表的倒数第N个节点
 * @date 2023/2/24 19:43
 */
public class liko19 {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //虚拟节点
        ListNode dummyhead=new ListNode(0);
        dummyhead.next=head;
        ListNode fast=dummyhead;
        ListNode show=dummyhead;
        //先让快指针走n+1步
       while (n-->=0){
           fast=fast.next;
       }
       //在快慢指针同时移动
       while (fast!=null){
           show=show.next;
           fast=fast.next;
       }
       //此时慢指针指向要删除元素的前一个元素
        show.next=show.next.next;
       return dummyhead.next;
    }


}

链表相交

环形链表II

package linkedlist;

import util.ListNode;

import java.util.List;

/**
 * @author zwf
 * @Package: linkedlist
 * @ClassName: liko142
 * @Description:
 * @date 2023/2/25 19:58
 */
public class liko142 {
    public ListNode detectCycle(ListNode head){
        ListNode slow=head;
        ListNode fast=head;
        while (fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
            if (slow==fast) {//有环
                //找入口
                ListNode index1=fast;
                ListNode index2=head;
                //两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
                while (index1!=index2){
                    index1=index1.next;
                    index2=index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}