不简单的数组增删改查-(算法通关村第三关青铜挑战)
-
初始化数组最基本的方式是循环赋值:
-
for(int i = 0; i < arr.length; i++){ arr[i] = i; }
-
但是这种方式在面试题中一般不行,因为很多题目会给定若干测试数组让你都能测试通过,例如给你两个数组 [0,1,2,3,5,6,8] 和 [1,4,5,6,7,9,10]。那这时候该如何初始化呢?显然不能用循环了,可以采用下面的方式:
-
int[] arr = new int[]{0,1,2,3,5,6,8}; int[] nums = {2, 5, 0, 4, 6, -10};
-
如果要测试第二组数据,直接将其替换就行。创建数组时大小就是元素的数量,是无法在插入元素的,如果需要增加新元素就不能这么用了。
查找一个元素
-
/** * * @param arr 要查找的数组 * @param size 已经存放的元素个数 * @param key 待查找的元素 * @return */ public static int findByElement(int[] arr, int size, int key){ for(int i = 0; i < size; i++){ if(arr[i] == key){ return i; } } return -1; }
-
还有一种很常见的情况,如果数组是递增的,此时查找时如果相等或者当前位置元素比目标值更大就停下了。你是否可以修改上面的代码来实现这个功能?
-
public static int findByElement2(int[] arr, int size, int key){ for(int i = 0; i < size; i++){ if(arr[i] > key){ System.out.println("key not exists in arr[]"); }else if(arr[i] == key){ return i; } } return -1; }
增加一个元素
-
/** * * @param arr * @param size 数组已经储存的元素数量,从1开始编号 * @param element 待插入的元素 * @return */ public static int addByElementSequence(int[] arr, int size, int element){ //判断size > arr.length if(size >= arr.length){ return -1; } int index = size;//新元素插入位置索引 for(int i = 0; i < size; i++){ if(element < arr[i]){ index = i; break; } } //元素后移 for(int j = size; j > index;j--){ arr[j] = arr[j-1]; } arr[index] = element; return index; }
删除一个元素
-
例如序列是1 2 3 4 5 6 7 8 9,要删除5,则应先遍历,找到5,然后从5开始执行删除操作,也就是从6开始逐步覆盖上一个元素,最终将序列变成1 2 3 4 6 7 8 9[9]。
-
/** * * @param arr 数组 * @param size 数组已经储存的元素数量,从1开始编号 * @param key 删除目标值 * @return */ public int removeByElement(int[] arr, int size, int key){ int index= -1; for(int i = 0; i < size; i++){ if(arr[i] == key){ index = i; break; } } if(index != -1){ for(int j = index + 1; j < size; j++){ arr[j-1] = arr[j]; } size--; } return size; }
单调数组问题
-
LeetCode896: 判断一个给定的数组是否为单调数组。
-
在 i 和 i+1 位置出现了 nums[i] > nums[i+1],而在另外一个地方 j 和 j+1 出现了 nums[j] < nums[j+1],那就说明不是单调。
-
public boolean isMonotonic(int[] nums){ boolean incr = true, decr = true; int n = nums.length; for(int i = 0; i < n-1; i++){ if(nums[i] > nums[i+1]){ incr = false; } if(nums[i] < nums[i+1]){ decr = false; } } return incr || decr; }
数组合并问题
-
LeetCode88: 给你两个按非递减顺序排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n,分别表示 nums1 和 nums2 中的元素数目。请你合并 nums2 到 nums1 中,使合并后的数组同样按非递减顺序排列。
-
最终合并的数组储存在数组 nums1 中,nums1 的初始长度为 m+n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0应忽略。nums2 的长度为n。
-
例子1: 输入:nums1 = [1, 2, 3, 0, 0, 0],m = 3,nums2 = [2, 5, 6],n = 3 输出:[1, 2, 2, 3, 5, 6] 解释:合并 [1, 2, 3,] 和 [2, 5, 6] 的结果是 [1, 2, 2, 3, 5, 6] -
对于有序数组的合并,一种简单的方法是先将B直接合并到A的后面,然后再对A排序。(没技术含量)。
-
public void merge1(int[] nums1, int nums1_len, int[] nums2, int nums2_len){ for(int i = 0; i < nums2_len; i++){ nums1[nums1_len + i] = nums2_len; } Arrays.sort(nums1); }
-
比较好的方式是从后向前插入,A和B的元素数量是固定的,所以排序后最远位置一定是A和B元素都最大的那个,依次类推,每次都找最大的那个从后向前填就可以了。
-
public void merge(int[] nums1, int nums1_len, int[] nums2, int nums2_len){ int i = nums1_len + nums2_len -1; int len1 = nums1_len-1, len2 = nums2_len-1; while(len1 >= 0 && len2 >= 0){ if(nums1[len1] <= nums2[len2]){ nums1[i--] = nums2[len2--]; }else if(nums1[len1] > nums2[len2]){ nums1[i--] = nums1[len1--]; } } //假如数组 A 或 B 还有剩余元素 while(len2 != -1){ nums1[i--] = nums2[len2--]; } while(len1 != -1){ nums1[i--] = nums1[len1--]; } }