- 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1
和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。
请你 合并 nums2
到 nums1
中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1
中。为了应对这种情况,nums1
的初始长度为 m + n
,其中前 m
个元素表示应合并的元素,后 n
个元素为 0
,应忽略。nums2
的长度为 n
。
class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { for (int i = 0; i != n; ++i) { nums1[m + i] = nums2[i]; } Arrays.sort(nums1); } }
2.删除有序数组中的重复项
给你一个 升序排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums
中唯一元素的个数。
考虑 nums
的唯一元素的数量为 k
,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums
,使nums
的前k
个元素包含唯一元素,并按照它们最初在nums
中出现的顺序排列。nums
的其余元素与nums
的大小不重要。 - 返回
k
。
设置标签
public int removeDuplicates(int[] nums) { if(nums == null || nums.length == 0) return 0; int p = 0; int q = 1; while(q < nums.length){ if(nums[p] != nums[q]){ nums[p + 1] = nums[q]; p++; } q++; } return p + 1; }
3.O(1) 时间插入、删除和获取随机元素
实现RandomizedSet
类:
RandomizedSet()
初始化RandomizedSet
对象bool insert(int val)
当元素val
不存在时,向集合中插入该项,并返回true
;否则,返回false
。bool remove(int val)
当元素val
存在时,从集合中移除该项,并返回true
;否则,返回false
。int getRandom()
随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。每个元素应该有 相同的概率 被返回。
你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1)
。
class RandomizedSet { HashMap<Integer, Integer> map; List<Integer> arr; int size; Random random; public RandomizedSet() { arr = new ArrayList<>(); map = new HashMap<>(); random = new Random(); size = 0; } public boolean insert(int val) { if (map.containsKey(val)) { return false; } arr.add(val); map.put(val, size); size++; return true; } public boolean remove(int val) { if (!map.containsKey(val)) { return false; } size--; int key = map.get(val); int end_val = arr.get(size); //交换末尾元素和当前元素 swapArr(key, size); swapMap(key, val, size, end_val); //删除末尾的值 arr.remove(size); map.remove(val); return true; } public void swapArr(int l, int r) { if (Objects.equals(arr.get(l), arr.get(r))) { return; } int temp = arr.get(l); arr.set(l, arr.get(r)); arr.set(r, temp); } public void swapMap(int l_key, int l_val, int r_key, int r_val) { if (l_key == r_key) { return; } map.put(l_val, r_key); map.put(r_val, l_key); } public int getRandom() { int pivot = random.nextInt(size); return arr.get(pivot); } }
4.反转字符串中的单词
给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
class Solution { public String reverseWords(String s) { StringBuilder builder = new StringBuilder(s); builder.reverse(); int len = 0; for (int i = 0; i < builder.length(); i++) { if (builder.charAt(i) == ' ') { continue; } int j = i; while (j < builder.length() && builder.charAt(j) != ' ') { j++; } if (len > 0) { builder.setCharAt(len++, ' '); } // len + k < j - 1 - k: [0, len + k] 已经是正序 && [j - 1 - k, j] 已经是正序 for (int k = 0; k < j - i && len + k < j - 1 - k; k++) { swap(builder, len + k, j - 1 - k); } len += j - i; i = j - 1; } builder.delete(len, builder.length()); return builder.toString(); } private void swap(StringBuilder builder, int i, int j) { char tmp = builder.charAt(i); builder.setCharAt(i, builder.charAt(j)); builder.setCharAt(j, tmp); } }
5.长度最小的子数组
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
我们申请一个临时数组 sums,其中 sums[i] 表示的是原数组 nums 前 i 个元素的和,题中说了 “给定一个含有 n 个 正整数 的数组”,既然是正整数,那么相加的和会越来越大,也就是sums数组中的元素是递增的。我们只需要找到 sums[k]-sums[j]>=s,那么 k-j 就是满足的连续子数组,但不一定是最小的,所以我们要继续找,直到找到最小的为止。怎么找呢,我们可以使用两个 for 循环来枚举,但这又和第一种暴力求解一样了,所以我们可以换种思路,求 sums[k]-sums[j]>=s 我们可以求 sums[j]+s<=sums[k],那这样就好办了,因为数组sums中的元素是递增的,也就是排序的,我们只需要求出 sum[j]+s 的值,然后使用二分法查找即可找到这个 k。
public int minSubArrayLen(int s, int[] nums) { int length = nums.length; int min = Integer.MAX_VALUE; int[] sums = new int[length + 1]; for (int i = 1; i <= length; i++) { sums[i] = sums[i - 1] + nums[i - 1]; } for (int i = 0; i <= length; i++) { int target = s + sums[i]; int index = Arrays.binarySearch(sums, target); if (index < 0) index = ~index; if (index <= length) { min = Math.min(min, index - i); } } return min == Integer.MAX_VALUE ? 0 : min; }