1.两个数的交集(350)

image.png

使用map
解题思路,分成以下4个小问题:
1.先遍历第一个数组,把数字和次数放进map,然后遍历第二个
2.遍历第一个时有如下2种情况:1.map中没有怎么办? 2.map中有怎么办?
3.遍历第二个也有上面2个问题
4.构建合适的数组。(不要用list,用list还需要多一次遍历)

使用双指针
解题思路:保证参数前小后大;构建容积不定的数组;构建双指针;比较双指针读数;处理结尾;

方法1:利用map

  1. public static int[] intersect2(int[] a1, int[] a2) {
  2. //之所以比较
  3. Map<Integer, Integer> map = new HashMap<>();
  4. for (int i = 0; i < a1.length; i++) {
  5. map.put(a1[i], map.getOrDefault(a1[i], 0) + 1);
  6. }
  7. int[] result = new int[a2.length];
  8. int index = 0;
  9. for (int i = 0; i < a2.length; i++) {
  10. int times = map.getOrDefault(a2[i], 0);
  11. if (times != 0) {
  12. result[index++] = a2[i];
  13. map.put(a2[i], times - 1);
  14. }
  15. }
  16. return Arrays.copyOfRange(result, 0, index);
  17. }
  18. /**
  19. * 分成以下4个小问题:
  20. * 1.先遍历第一个数组,把数字和次数放进map,然后遍历第二个
  21. * 2.遍历第一个时有如下2种情况:1.map中没有怎么办? 2.map中有怎么办?
  22. * 3.遍历第二个也有上面2个问题
  23. * 4.构建合适的数组。(不要用list,用list还需要多一次遍历)
  24. * <p>
  25. * 学到的知识点:
  26. * 1.map要获取不确定是否存在的元素:getOrDefault()
  27. * 2.构建长度不确定的数组。可以先规定最大长度,然后CopyOfRange()。另外构建数组的时候一定要有指针index
  28. */

方法2:进阶,使用双指针。

  1. public static int[] betterInteract(int[] a1, int[] a2) {
  2. if (a1.length > a2.length) {
  3. return betterInteract(a2, a1);
  4. }
  5. int index = 0, rindex = 0;
  6. int[] result = new int[a1.length];
  7. for (int i = 0; i < a1.length; i++) {
  8. while (index < a2.length && a2[index] < a1[i]) {
  9. index++;
  10. }
  11. if (a2[index] == a1[i]) {
  12. result[rindex++] = a1[i];
  13. }
  14. }
  15. //保证参数前小后大;构建容积不定的数组;构建双指针;比较双指针读数;处理结尾;
  16. return Arrays.copyOfRange(result,0,rindex);
  17. }

学到的知识点:1-6

1.map要获取不确定是否存在的元素:getOrDefault()
2.构建容积不定的数组。可以先规定最大长度,然后CopyOfRange()。另外构建数组的时候一定要有指针index

3.保证参数前小后大;(调用函数自身)
4.构建双指针;使用for和 一个指针。
5.比较双指针读数;(大于,小于,等于)
6.处理结尾;(任意数组到头了)

2.最长公共子前缀(14)

image.png
思路:选基准,依次把剩下的数据和基准比较; 寻找两个字符串的最长共同前缀; 分析并处理最后可能的各种结果

  1. public static String getLargestLengthFix(String[] strs) {
  2. if(strs.length == 0) return "";
  3. String pivot = strs[0];
  4. for (int i = 1; i < strs.length; i++) {
  5. while (strs[i].indexOf(pivot) != 0) {
  6. pivot = pivot.substring(0,pivot.length()-1);
  7. if(pivot.equals("")) return "";
  8. }
  9. }
  10. return pivot;
  11. }

学到的知识点:7-8

7.寻找两个字符串的最长公共子前缀。(String.substring())
8.如果在遍历过程中,已经产生了最终结果,就直接返回。 if() return

3.买卖股票的最佳时机(122)

image.png
image.pngimage.png

  1. public static int maxProfit(int[] prices) {
  2. int profit = 0;
  3. for (int i = 0; i < prices.length-1; i++) {
  4. int temp = prices[i+1] - prices[i];
  5. if(temp>0) {
  6. profit += temp;
  7. }
  8. }
  9. return profit;
  10. }

4.旋转数组

  1. public static int gcd(int min, int max) {
  2. return max > 0 ? gcd(max, min % max) : min; //辗转相除法求gcd
  3. }
  4. //1.确定循环次数 2.确定每趟的终止条件 3.需要继续循环的交换位置(固定一边交换位置)
  5. public static int[] traverse(int[] arr, int k) {
  6. int n = arr.length;
  7. k = k % n;
  8. int count = gcd(k, n);
  9. for (int start = 0; start < count; start++) {
  10. int current = start;
  11. int prev = arr[current];
  12. do {
  13. int pos = (current + k) % n;
  14. int temp = arr[pos];
  15. arr[pos] = prev;
  16. prev = temp;
  17. current = pos;
  18. } while (current != start);
  19. }
  20. return arr;
  21. }

学到的知识点9-12

9.数组以k个为一组循环,循环次数是n和k的公约数。
10.最大公约数的代码。
11.k组循环每组终止条件:记录开始指针,当前指针==开始指针,就结束
12.固定一边交换位置:正常的交换,少一步填坑就行了。

5.删除数组中的重复元素

首先数组是有序数组。
这种要统计数组中每个数出现次数的。要么用hash,但是如果要求本地删除(空间复杂度为1),那就一定得是有序的了。
如果不是有序的,仍然要空间复杂度为1呢?那就时间换空间。用复杂度为O(n^2)的算法。两个for循环。
第一个for循环是遍历arr数组,第二个for循环是遍历arr前面已经整理好的部分。