数组类:
1.原地去除数组中重复的元素
/**方法1 申请一个和nums大小一样的数组tmpNums,
* 然后遍历nums中的元素,对每个元素判断是否在tmpNums出现过,
* 如果出现过,那么就不放到新数组里面,也就是不做处理;
* 如果没有出现过,那么就把它放到新的数组里面
* 这种方法数组原来的相对顺序可以保证
* 时间复杂度是n^2和空间复杂度是n
*/
public int removeDuplicates(int[] nums){
if(nums.length==0) return 0;
int[] tmpNums=new int[nums.length];
tmpNums[0]=nums[0];
int index=1;
for(int i=0;i<nums.length;i++)
{
int j=0;
for(;j<index;j++)
{
if(tmpNums[j]==nums[i]) break;
}
if(j==index)
{
tmpNums[index++]=nums[j];
}
}
nums=tmpNums;
return nums;
}
/**
* 方法2 先对nums排序,排序后重复的元素一定相邻
* 然后遍历nums,并用index来表示不重复的元素应该存放的下标
* 如果当前遍历的元素和它的前一个元素相等,那么它是重复的,遍历下一个
* 如果不等,说明不重复,那么当前元素存放到数组中下标为index的地方,index++
* 这样遍历下来,不同元素都放到原数组的前面去了
* 采用这种方法,得到的是有序数组,数组原来的位置改变了
* 时间和空间复杂度是对应排序算法的复杂度
*/
public int removeDuplicates(int[] nums){
if (nums.length == 0) { return 0; }
Arrays.sort(nums);
int index = 1;
for (int i = 1, len=nums.length; i < len; i++){
if (nums[i] != nums[i-1]){
nums[index++] = nums[i];
}
}
return index;
}
/**
* 方法3 利用直接插入排序的思想,将数组分成两部分
* 左边认为是满足要求的不重复的部分,初始为1个元素nums[0]
* 右边是等待遍历的部分,不断遍历右边的元素
* 同样是index来表示左边部分不重复的元素应该存放的下标
* 对于当前遍历的元素,通过第二层循环遍历左边部分0到index的元素
* 如果有元素和当前元素相等,说明是重复的,那么不处理
* 否则,说明不重复,那么插入到下标index的地方,index++
* 采用这种方法,数组的相对顺序得到保证
* 此方法是对方法1的改进
* 时间复杂度为n^2,空间复杂度为1
* @param nums
* @return
*/
public int removeDuplicates(int[] nums){
if (nums.length == 0) return 0;
int index = 1;//标记没有重复的位置的指针
for (int i = 1, len = nums.length; i < len; i++){
int j = 0;
for(; j < index; j++){
//判断当前遍历的第i个元素在index指针之前不重复的元素中是否出现过
if (nums[j] == nums[i]) {
break;
}
}
//替换已重复元素
if(j == index) {
nums[index++] = nums[i];
}
}
return index;
}
/**
* 方法4 利用Java容器来帮助判断元素是否重复,可以使用Set Map List等
* 这里可以利用Set容器不能存放相同元素的特性
* 用index来表示不重复的元素应该存放的下标
* 如果当前元素可以成功加入到Set容器中,说明这个元素没有重复
* 那么当前元素就可以放到下标index的地方,index++
* 如果add失败,说明元素重复,不做操作
* 此方法同样是把不重复的数组放到数组的前面,并可以保证元素的相对位置不变,不过需要额外的Set容器空间
* 时间复杂度n,空间复杂度n
* @param nums
* @return
*/
public int removeDuplicates(int[] nums){
if (nums.length == 0) return 0;
Set<Integer> set = new HashSet<Integer>();
int index = 0;
for (int i = 0, len = nums.length; i < len; i++) {
if(set.add(nums[i])) {
nums[index++] = nums[i];
}
}
return index;
}
2.旋转数组
/**
*思路1:利用temp存储nums[nums.length-1]的值,依次将元素右移一位,重复k次
*/
public void rotate(int[] nums, int k) {
int len = nums.length;
if(len == 0||(k%=len) == 0) {return;}
for(int i=1;i<=k;i++){
int temp=nums[len-1];
for(int j=len-2;j>=0;j--){
nums[j+1]=nums[j];
}
nums[0]=temp;
}
return;
}
/**
* 思路2:旋转后元素nums[i]的位置为(i+k)% nums.length
* 1.新建一个同样长度大小的tempnums[]
* 2.若想空间复杂度为O(1),可进行原地置换
*/
public void rotate(int[] nums, int k) {
int len = nums.length;
if(len == 0||(k%=len) == 0) {return;}
int[] tempnums=new int[len];
for(int i=0;i<len;i++){
tempnums[i]=nums[i];
}
for(int i=0;i<len;i++){
nums[(i+k)%len]=tempnums[i];
}
return;
}
/**
* 思路3:先反转前n-k个元素,再反转后k个元素,然后再将整个数组反转,反转的实现即首尾两个数字交换
*/
public void rotate(int[] nums, int k) {
int len = nums.length;
if(len == 0||(k%=len) == 0) {return;}
reverse(nums,0,len-k-1);
reverse(nums,len-k,len-1);
reverse(nums,0,len-1);
}
public static void reverse(int nums[],int start,int end){
int temp;
while(start<end && start>=0){
temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}