题外话: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;
}
}