数组
二分查找
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;
}
}
有序数组的平方
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;
}
}