陣列去重 演算法實現
阿新 • • 發佈:2019-02-11
最近同學在面試的過程中,連續被問道了這個問題,因此做個總結!
package com.lee.wait;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* ArrayUniue 陣列去重的問題
*
* @author wait
*
*/
public class ArrayUnique {
/**
* 方法1 就是申請一個和nums大小一樣的陣列tmpNums,
* 然後遍歷nums中的元素,對每個元素判斷是否在tmpNums出現過,
* 如果出現過,那麼就不放到新數組裡面,也就是不做處理;
* 如果沒有出現過,那麼就把它放到新的數組裡面
* 這種方法陣列原來的相對順序可以保證
* 時間複雜度是n^2和空間複雜度是n
*
* @param nums 輸入需要去重的陣列
* @return 返回去重後陣列的長度
*/
public static int unique1(int[] nums) {
if (nums.length == 0) {
return 0;
}
int[] tmpNums = new int[nums.length];
tmpNums[0] = nums[0];
int index = 1;
for (int i = 1, len = nums.length; i < len; i++) {
int j = 0;
for (; j < index; j++) {
if (tmpNums[j] == nums[i]) {
break;
}
}
if (j == index) {
tmpNums[index++] = nums[i];
}
}
nums = tmpNums;
return index;
}
/**
* 方法2 先對nums排序,排序後重復的元素一定相鄰,
* 然後遍歷nums,並用index來表示不重複的元素應該存放的下標,
* 如果當前遍歷的元素和他的前一個元素相等,那麼他是重複的,遍歷下一個;
* 如果不等,說明不是重複,那麼當前元素存放到陣列中下標為index的地方,index++
* 這樣遍歷下來,不同的元素都放到元陣列的前面去了。
* 這種方法,得出來的是排序過得,陣列原來的相對位置改變了。
* 時間複雜度和空間複雜度都是對應排序演算法的複雜度
*
* @param nums 輸入需要去重的陣列
* @return 返回去重後陣列的長度
*/
public static int unique2(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 static int unique3(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++) {
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容器的空間。
* 在javascript語言中,使用map={},物件的概念來判斷 通過物件的屬性和值來拍段,和使用Map是同樣的原理。
* 時間複雜度是n,空間複雜度也是n
*
* @param nums 輸入需要去重的陣列
* @return 返回去重後陣列的長度
*/
public static int unique4(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;
}
/**
* printNums 列印陣列的從0到length元素
*
* @param nums 輸入陣列
* @param length 列印長度
*/
public static void printNums(int[] nums, int length) {
for (int i = 0; i < length - 1; i++) {
System.out.print(nums[i] + " ");
}
System.out.println(nums[length - 1]);
}
/**
* main 函式
*
* @param args
*/
public static void main(String[] args) {
int[] nums = { 21, 321, 432, 213, 43, 23, 213, 4, 231, 2321, 432, 12, 3, 123, 23, 12, 3, 2, 4, 23, 1, 2312, 4,
33, 21, 31, 23 };
printNums(nums, nums.length);
int len = uniue4(nums);
printNums(nums, len);
}
}