牛客网leetcode刷题之数组(常数空间找数字、字典序最大排列、删除目标数、删除重复数)

题外话:2020庚子年,却是一个不如意的开始,全球各地都遭受带了自然界的伤害。这个寒假武汉的疫情令人痛心,科比也遭遇不幸。。。,不论如何都希望我们能够度过这次的难关,春暖花开时,愿你我不负好时光,希望人类能够珍爱生命、保护自然。

--------------------------------------------------------

1.题目一描述:
给出一个无序的整数型数组,求不在给定数组里的最小的正整数,
你需要给出时间复杂度在O(n)之内并且空间复杂度为常数级的算法
题目一分析:
借鉴大神的思路,首先将数组中的数放在自己对应的位置上,然后遍历数组,不对应的位置的下标数字+1就为该数组中不存在的最小正整数,若全部存在则数组的下标+1。
代码如下:

public class Solution {
    public int firstMissingPositive(int[] A) {
        int n = A.length;
        //遍历数组将对应的数字放置在相应的位置
        for(int i=0;i<n;i++ ){
            while(A[i]>0 && A[i]<=n && A[i]!=A[A[i]-1]){
                int tmp = A[A[i]-1];
                A[A[i]-1]=A[i];
                A[i] = tmp;
            }
        }
        //找到第一个位置不符合的元素
        for(int i=0;i<n;i++){
            if(A[i]!=i+1)return i+1;
        }
        return n+1;
    }
}

2.题目二描述:
实现函数next permutation(下一个排列):将排列中的数字重新排列成字典序中的下一个更大的排列。将排列中的数字重新排列成字典序中的下一个更大的排列。
如果不存在这样的排列,则将其排列为字典序最小的排列(升序排列)
需要使用原地算法来解决这个问题,不能申请额外的内存空间
题目二分析:
大神思路:先将数组从后向前寻找,如果一直是递增的则将数组反转,否则找到第一个不满足递增条件的元素的位置i,继续从后向前遍历,找到第一个大于该位置前一个元素即i-1位置的数将两个数交换,将i位置之后的元素进行逆序即为所求。
代码如下:

public class Solution {
    public void nextPermutation(int[] num) {
         int len = num.length;
	        int i = len-1;
		//从后向前找到不递增的位置i
	        for(;i > 0;i--) {
	        	if(num[i] > num[i-1])	break;
	        }
	        if(i==0) {//如果全部逆向增序则将数组反转
	        	orderArray(0,len-1,num);
	        }else {//从后向前找到第一个大于i-1位置元素的数,将其与之交换,再将i之后的位置进行逆序,输出
	        	for(int j=len-1;j>=i;j--) {
		        	if(num[i-1]<num[j]) {
		        		swap(i-1,j,num);
		        		orderArray(i,len-1,num);
		        		break;
		        	}
		        }
	        }
    }
    //将数组中相应位置的元素进行反转
     public  void orderArray(int left,int right,int[] num) {
     	for(;left < right;left++,right--) {
     		swap(left,right,num);
     	}
	 }
	 //将数组中的i位置与j位置的数字进行交换
	 public  void swap(int i,int j,int[] num) {
		 int tmp = num[i];
		 num[i] = num[j];
		 num[j] = tmp;
	 }
}

3.题目三描述:
给定一个数组和一个值,使用就地算法将数组中所有等于这个值的元素删除,并返回新数组的长度。
题目三分析:
将所有等于elem的元素放置在该数组的最后位置,使用两个指针,一个从前向后,一个从后向前,从后向前的指针为了压缩数组,从前向后的指针为了寻找前边与elem相等的元素,将其放置在数组右边指针的位置。
代码如下:

public class Solution {
    public int removeElement(int[] A, int elem) {
        if(A.length==0) return A.length;
        int left = 0;//数组起始位置
	     int right = A.length-1;//数组结束位置
	     if(left==right && A[left]==elem) return 0;
	     while(left < right) {
	         //如果右边位置一直相等,则右边指针一直向左移动,缩小数组长度
	    	 while(left<right && A[right] == elem) {
	    		 if(right==0) return 0;
	    		 right--;
	    	 }
	    	 //左边指针如果与elem相等,则将其元素与右边进行交换,将右边指针向左移动压缩数组
	    	 if(left<right &&A[left] == elem) {
	    		 swap(left,right,A);
	    		 right--;
	    	 }
	    	 if(left < right) left++;
	     }
	     //当前左边指针指向的元素如果与elem相等,那么数组长度为left的值,否则数组长度为left的值+1
		 return  A[left]==elem?left:left+1;
    }
    //将数组中的i位置的元素与j位置的元素进行交换
     public  void swap(int i,int j,int[] num) {
		 int tmp = num[i];
		 num[i] = num[j];
		 num[j] = tmp;
	 }
}

4.题目四描述:
给定一个已排序的数组,使用就地算法将重复的数字移除,使数组中的每个元素只出现一次,返回新数组的长度。
不能为数组分配额外的空间,你必须使用常熟级空间复杂度的就地算法。
题目四分析:
使用两个指针,第一个指针用于记录当前组建的新数组最后一个元素的位置,第二个指针用于遍历多余的元素,第二个指针遇到与第一个指针不相等的元素时,将第一个元素下一个位置放置第二个指针指向的元素,一次类推,第一个指针始终为组建的新数组,第二个指针结束时,返回第一个指针+1,即为新数组的长度。
代码如下:

public class Solution {
    public int removeDuplicates(int[] A) {
    	//数组中没有元素或者只有一个元素不存在重复元素
         if(A.length==0||A.length==1)return A.length;
	     int oneindex = 0;
	     int twoindex = 0;
	     //一次将数组中不同的元素进行只挑选一个放置在最前面
	     for(;twoindex < A.length;) {
	    	 if(A[oneindex] == A[twoindex])twoindex++;
	    	 else {
	    		 swap(oneindex+1,twoindex,A);
	    		 oneindex++;
	    		 twoindex++;
	    		 }
	     }
		 return oneindex+1;
    }
    //将数组中i位置的元素与j位置的元素进行交换
    public  void swap(int i,int j,int[] num) {
		 int tmp = num[i];
		 num[i] = num[j];
		 num[j] = tmp;
	 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值