其他算法题目


数组中重复的数据

在这里插入图片描述

在这里插入图片描述

解题思路:

遍历数组,假如当前数字nums[i] = x,则把下标为x-1的数字变成负数 (nums[x-1] = -nums[x-1])。
继续遍历,若第二次遇到x的时候,我们去查找x-1位置的数字是否为负数,是的话则说明之前遇到过了x,把它加入答案中。

class Solution {
public:

    vector<int> findDuplicates(vector<int>& nums) {
        vector<int>res;
        for(int x:nums){
            if(nums[abs(x)-1]<0)res.push_back(abs(x));
            else{
                nums[abs(x)-1]*=-1;
            }
        }
        return res;
    }
};

在这里插入图片描述


将整数转换为两个无零整数的和

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    //双指针
    bool isHave0(int x){
        while(x>0){
            if(x%10==0)return true;
            x/=10;
        }
        return false;
    }
    vector<int> getNoZeroIntegers(int n) {
        int left=1;
        vector<int>ans;
        while(left<=(n>>1)){
            if(isHave0(left)||isHave0(n-left)){
                left++;
            }else{
                ans.push_back(left);
                ans.push_back(n-left);
                return ans;
            }
        }
        return ans;
    }
};

在这里插入图片描述


矩形重叠

在这里插入图片描述
在这里插入图片描述

解题思路:

矩形如果不重叠,从x轴和y轴上看两个矩形就变成了两条线段,这两条线段肯定是不相交的,也就是说左边的矩形的最右边小于右边矩形的最左边 。

class Solution {
public:
    bool isRectangleOverlap(vector<int>& rec1, vector<int>& rec2) {


        //只有在x轴上和y轴上的投影同时是一条线段,两个矩形才重叠
        int x10=rec1[0];
        int x11=rec1[2];
        int x20=rec2[0];
        int x21=rec2[2];
        if(x21<=x10||x20>=x11)return false;
        int y10=rec1[1];
        int y11=rec1[3];
        int y20=rec2[1];
        int y21=rec2[3];
        if(y21<=y10||y20>=y11)return false;
        return true;

    }
};

在这里插入图片描述


岛屿的周长


在这里插入图片描述
在这里插入图片描述

class Solution {
    public int islandPerimeter(int[][] grid) {
        int ans=0;
        for(int row=0;row<grid.length;++row){
            for(int col=0;col<grid[0].length;++col){
                if(grid[row][col]==1){
                    if(row==0){
                        ans++;
                    }
                    if(row>0&&grid[row-1][col]==0){
                        ans++;
                    }
                    if(row==grid.length-1){
                        ans++;
                    }
                    if(row<grid.length-1&&grid[row+1][col]==0){
                        ans++;
                    }
                    if(col==0){
                        ans++;
                    }
                    if(col>0&&grid[row][col-1]==0){
                        ans++;
                    }
                    if(col==grid[0].length-1){
                        ans++;
                    }
                    if(col<grid[0].length-1&&grid[row][col+1]==0){
                        ans++;
                    }

                }
            }
        }

        return ans;
    }
}

在这里插入图片描述



下载插件

在这里插入图片描述
在这里插入图片描述

说明:

暴力递归答案是正确的,但是运行超时
动态规划没改对
最后尝试了打表法,用暴力递归跑一些样例,从中总结出规律,得到复杂度 O ( l o g N ) O(logN) O(logN)


class Solution {
    //暴力递归
    //当前还剩下rest个插件,当前来到了第index分钟,当前可以下载的插件数量
    public int process(int rest,int index,int num){
        if(rest<=0){//插件已经全部下载完毕
            return index-1;
        }
        //插件尚未下载完毕
        if(num>=rest){
            return index;
        }
        //第index分钟用来带宽加倍
        
        //第index分钟用来下载插件
        return Math.min(process(rest,index+1,num*2),process(rest-num,index+1,num));
    }
    public int DP(int n){
        //index: 1~n+1  num :0~n*2  rest: 0~n  
        int[][][] dp=new int[n+2][n*2+1][n+1];
        for(int level=1;level<n+1;++level){
            for(int row=0;row<=n*2;++row){
                dp[level][row][0]=level-1;
            }
            for(int row=n*2;row>=0;--row){
                for(int col=1;col<=n;++col){
                    if(row>=col){
                        dp[level][row][col]=level;
                    }else{
                        dp[level][row][col]=Math.min(row*2<=n*2?dp[level+1][row*2][col]:Integer.MAX_VALUE,dp[level+1][row][col-row]);
                    }
                }
            }
        }
        return dp[1][0][n];
    }
    public int leastMinutes(int n) {//打表法AC
        if(n<3)return n;
    	//得到n是严格大于哪个2的幂数
    	for(int i=1;;++i) {//O(logN)
    		if((1<<i)<n&&(1<<(i+1))>=n)return i+2;
    	}
        
    }
}

划分数组

在这里插入图片描述

在这里插入图片描述

import java.util.Scanner;

public class Main {
	
	
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int[] arr=new int[n];
		for(int i=0;i<n;++i) {
			arr[i]=scan.nextInt();
		}
		int max=Integer.MIN_VALUE;
		for(int i=0;i<n;++i) {
			max=Math.max(max, arr[i]);
		}
		int a=Math.abs(max-arr[0]);
		int b=Math.abs(max-arr[n-1] );
		System.out.println(Math.max(a, b));
	}

}

在这里插入图片描述



最长可整合子数组长度

在这里插入图片描述

在这里插入图片描述

import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int[] arr=new int[n];
		for(int i=0;i<n;++i) {
			arr[i]=scan.nextInt();
		}
		int ans=0;
		for(int L=0;L<n;++L) {
			
			int min=Integer.MAX_VALUE;
			int max=Integer.MIN_VALUE;
			for(int R=L;R<n;R++) {
				min=Math.min(min, arr[R]);
				max=Math.max(max, arr[R]);
				if(max-min==R-L) {
					ans=Math.max(ans, R-L+1);
				}
            }
		}
		System.out.println(ans);
	}

}

在这里插入图片描述



斐波那契数列问题 O ( l o g N ) O(logN) O(logN) 的解法

在这里插入图片描述

import java.util.Scanner;

public class Main {
	
	public static long process(long n) {
		long[][] help=new long[][] {{1,1},{1,0}};
		long[][] res=MatrixPower(help,n-2);
		return (res[0][0]%1000000007+res[1][0]%1000000007)%1000000007;
	}
	public static long[][] MatrixPower(long[][] help,long x){
		long[][] tmp=help;
		long[][] ans={{1,0},{0,1}};
		for(;x!=0;x>>=1) {
			if((x&1)!=0) {
				ans=MatrixMultiply(ans,tmp);
			}
			tmp=MatrixMultiply(tmp,tmp);
		}
		
		return ans;
	}
	public static long[][] MatrixMultiply(long[][] a,long[][] b){
		long[][] res=new long[2][2];
		for(int i=0;i<2;++i) {
			for(int j=0;j<2;++j) {
				for(int k=0;k<2;++k) {
					res[i][j]+=(a[i][k]%1000000007)*(b[k][j]%1000000007);
				}
			}
		}
		return res;
	}
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		long n=scan.nextLong();
		if(n<3)System.out.println(1);
		else {
			long ans=process(n);
			System.out.println(ans);
		}
		
	}
	

}

在这里插入图片描述



城市路径

在这里插入图片描述

在这里插入图片描述

public class Solution {
	/**
	 *	将路径数组变为统计数组
	 *	输入:代表一张图的数组paths
	 *	将paths数组变为距离数组numArr
	 */
    
	public void pathArrToNumArr(int[] paths) {
        
        int origin=0;
        int last=0;
        int next=0;
        for(int i=0;i<paths.length;++i) {
        	if(i==paths[i]||paths[i]<0)continue;//首都或者已经调整过的城市就跳过
        	origin=i;
        	last=i;
        	next=paths[i];
        	while(next!=paths[next]&&paths[next]>=0) {
        		int tmp=paths[next];
        		paths[next]=last;
        		last=next;
        		next=tmp;
        	}
        	if(next==paths[next]) {//遇到了首都
        		next=last;
        		int p=0;
        		while(next!=origin) {
        			last=paths[next];
        			paths[next]=--p;
        			next=last;	
        		}
        		paths[next]=--p;
        		
        	}else {//
        		int p=paths[next];
        		next=last;
        		while(next!=origin) {
        			last=paths[next];
        			paths[next]=--p;
        			next=last;
        		}
        		paths[next]=--p;
        	}
        	
        }
        
        
        //System.out.println("每个城市到首都的距离: "+Arrays.toString(paths));
        int index,distance;
        
        for(int i=0;i<paths.length;++i) {
        	if(i==paths[i]) {
        		paths[i]=0;
        		break;
        	}
        }
        for(int i=0;i<paths.length;++i) {
        	if(paths[i]<0) {//i位置可以开始跳转,否则直接跳过
//            	origin=i;
            	index=i;
            	distance=Math.abs(paths[index]);
            	paths[index]=0;
            	while(true){
            		if(paths[distance]>=0) {
            			paths[distance]++;
            			if(paths[index]<0)
            			paths[index]=0;
            			break;
            		}
            		int tmp=Math.abs(paths[distance]);
            		index=distance;
            		paths[distance]=1;
            		distance=tmp;
            	}
        	}
        
        }
        paths[0]=1;//后面的都不会跳到0位置
        //System.out.println(Arrays.toString(paths));
        
        
	}
}

在这里插入图片描述



分糖果问题

在这里插入图片描述
在这里插入图片描述

import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int[] arr=new int[n];
		for(int i=0;i<n;++i) {
			arr[i]=scan.nextInt();
		}
		int[] left=new int[n];
		int[] right=new int[n];
		left[0]=1;
		right[n-1]=1;
		for(int i=1;i<n;++i) {
			if(arr[i]>arr[i-1]) {
				left[i]=left[i-1]+1;
			}else {
				left[i]=1;
			}
		}
		for(int i=n-2;i>=0;--i) {
			if(arr[i]>arr[i+1]) {
				right[i]=right[i+1]+1;
			}else {
				right[i]=1;
			}
		}
		int ans=0;
		for(int i=0;i<n;++i) {
			ans+=Math.max(left[i], right[i]);
		}
		System.out.println(ans);
	}

}

在这里插入图片描述



分糖果问题进阶

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import java.util.Scanner;

public class Main {
	
	public static void main(String[] args) {
		Scanner scan=new Scanner(System.in);
		int n=scan.nextInt();
		int[] arr=new int[n];
		for(int i=0;i<n;++i) {
			arr[i]=scan.nextInt();
		}
		int[] left=new int[n];
		int[] right=new int[n];
		left[0]=1;
		right[n-1]=1;
		for(int i=1;i<n;++i) {
			if(arr[i]>arr[i-1]) {
				left[i]=left[i-1]+1;
			}else if(arr[i]==arr[i-1]){
				left[i]=left[i-1];
			}else {
				left[i]=1;
			}
		}
		for(int i=n-2;i>=0;--i) {
			if(arr[i]>arr[i+1]) {
				right[i]=right[i+1]+1;
			}else if(right[i]==right[i+1]){
				right[i]=right[i+1];
			}else {
				right[i]=1;
			}
		}
		int ans=0;
		for(int i=0;i<n;++i) {
			ans+=Math.max(left[i], right[i]);
		}
		System.out.println(ans);
	}

}

在这里插入图片描述





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值