LeetCode之数组的相对排序

题目:
给你两个数组,arr1 和 arr2,

  • arr2 中的元素各不相同
  • arr2 中的每个元素都出现在 arr1 中
    对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾
    方法一:计数排序
    算法思路:
  • 这一题第一反应是自定义比较函数,然后再进行排序,但是做完之后参考^2 发现,最简单的是用计数排序,充分利用了题目所给提示信息
  • 思路也很清晰,先将arr1中的数全都记录到数组count中,然后遍历arr2的同时,将arr2中的数置入arr1,注意由于arr2中的数在arr1中也出现了,所以直接从count中取出即可
  • 处理好arr2之后,再处理剩下的数字,一格一格往里填就好了
class Solution {
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        int[] count = new int[1001];
        // 将 arr1 中的数记录下来
        for (int num1 : arr1) {
            count[num1]++;
        }
        // 先安排 arr2 中的数
        int i = 0;
        for (int num2 : arr2) {
            while (count[num2] > 0) {
                arr1[i++] = num2;
                count[num2]--;
            }
        }
        // 再排剩下的数
        for (int num1 = 0; num1 < count.length; num1++) {
            while (count[num1] > 0) {
                arr1[i++] = num1;
                count[num1]--;
            }
        }
        return arr1;
    }
}

方法二:自定义比较函数

  • 这一题的思路很简单,依照要求,自定义一个比较函数,然后进行排序即可
  • 按题目要求我们知道,假设我们按升序排序,对于两个元素num1,num2,他们的比较有三种情况
  1. 都存在于arr2中,按他们的下标进行比较,可类比为靠前的数更小
  2. 其中一个存在于arr2,那么存在与arr2中的数靠前排,可认为更小
  3. 两个数都不存在于arr2,那么很简单,直接比较两个数大小即可
  • 根据以上思路很容易想到用一个HashMap存储arr2中元素和小标的对应关系,便于比较
    自定义排序代码:
Map<Integer, Integer> record = new HashMap<>(arr2.length);
for (int i = 0; i < arr2.length; i++) {
    record.put(arr2[i], i);
}
public boolean less(int num1, int num2) {
    if (record.containsKey(num1) && record.containsKey(num2)) {
        return record.get(num1) < record.get(num2);
    } else if (record.containsKey(num1)) {
        return true;
    } else if (record.containsKey(num2)) {
        return false;
    } else {
        return num1 < num2;
    }
}

方法三:lamdba表达式

class Solution {
    Map<Integer, Integer> record;
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        record = new HashMap<>(arr2.length);
        for (int i = 0; i < arr2.length; i++) {
            record.put(arr2[i], i);
        }
        List<Integer> res = Arrays.stream(arr1).boxed().collect(Collectors.toList());//arr1转为list

        Collections.sort(res, (num1, num2) -> {
            if (record.containsKey(num1) || record.containsKey(num2)) {
                return record.getOrDefault(num1, 1000) - record.getOrDefault(num2, 1000);//当Map集合中有这个key时,就使用这个key值,如果没有就使用默认值defaultValue
            } else {
                return num1 - num2;
            }
        });
        //mapToInt:每个元素对应的结果,因为从容器中取出来的值是Object,所以要转为int
        return res.stream().mapToInt(i -> i).toArray();
    }
}

方法四:快速排序:
快速排序思路:选择一个元素作为标准,其它元素与该元素比较,比该标准元素小的放前面

class Solution {
    Map<Integer, Integer> record;
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        record = new HashMap<>(arr2.length);
        for (int i = 0; i < arr2.length; i++) {
            record.put(arr2[i], i);
        }
        quickSort(arr1, 0, arr1.length - 1);
        return arr1;
    }
    public void quickSort(int[] arr, int lo, int hi) {
        if (lo >= hi) return;
        int j = partition(arr, lo, hi);
        quickSort(arr, lo, j - 1);
        quickSort(arr, j + 1, hi);
    }
    public int partition(int[] arr, int lo, int hi) {
        int temp = arr[hi];//最右边那个作为标准
        int j = lo;
        for (int i = lo; i < hi; i++) {
            if (less(arr[i], temp)) {//i位置的数与最右边那个相比较
                swap(arr, i, j++);
            }
        }
        swap(arr, j, hi);
        return j;
    }
    public void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    public boolean less(int num1, int num2) {
        if (record.containsKey(num1) && record.containsKey(num2)) {
            return record.get(num1) < record.get(num2);
        } else if (record.containsKey(num1)) {
            return true;
        } else if (record.containsKey(num2)) {
            return false;
        } else {
            return num1 < num2;
        }
    }
}

方法五:归并排序

class Solution {
    Map<Integer, Integer> record;
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        record = new HashMap<>(arr2.length);
        for (int i = 0; i < arr2.length; i++) {
            record.put(arr2[i], i);
        }
        mergeSort(arr1, 0, arr1.length - 1);
        return arr1;
    }
    public void mergeSort(int[] arr, int lo, int hi) {
        if (lo >= hi) return;
        int mid = lo + (hi - lo >> 1);
        mergeSort(arr, lo, mid);
        mergeSort(arr, mid + 1, hi);
        merge(arr, lo, mid, hi);
    }
    public void merge(int[] arr, int lo, int mid, int hi) {
        int[] temp = new int[hi - lo + 1];
        int i = lo;
        int j = mid + 1;
        for (int k = 0; k < temp.length; k++) {//归并
            if (i > mid) {//前半部分排完
                temp[k] = arr[j++];
            } else if (j > hi) {//后半部分排完
                temp[k] = arr[i++];
            } else if (less(arr[i], arr[j])) {
                temp[k] = arr[i++];
            } else {
                temp[k] = arr[j++];
            }
        }
        for (int k = 0; k < temp.length; k++) {//拷贝
            arr[lo + k] = temp[k];
        }
    }
    public void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    public boolean less(int num1, int num2) {
        if (record.containsKey(num1) && record.containsKey(num2)) {
            return record.get(num1) < record.get(num2);
        } else if (record.containsKey(num1)) {
            return true;
        } else if (record.containsKey(num2)) {
            return false;
        } else {
            return num1 < num2;
        }
    }
}

方法六:希尔排序

class Solution {
    Map<Integer, Integer> record;
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        record = new HashMap<>(arr2.length);
        for (int i = 0; i < arr2.length; i++) {
            record.put(arr2[i], i);
        }
        shellSort(arr1);
        return arr1;
    }
    public void shellSort(int[] arr) {
        int len = arr.length;
        int h = 0;
        while (h < len / 3) {
            h = 3 * h + 1;//算最长步长
        }
        while (h >= 1) {
            for (int i = h; i < len; i++) {
                for (int j = i; j >= h && less(arr[j], arr[j - h]); j -= h) {
                    swap(arr, j, j - h);
                }
            }
            h /= 3;
        }
    }
    public void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    public boolean less(int nums1, int nums2) {
        if (record.containsKey(nums1) && record.containsKey(nums2)) {
            return record.get(nums1) < record.get(nums2);
        } else if (record.containsKey(nums1)) {
            return true;
        } else if (record.containsKey(nums2)) {
            return false;
        } else {
            return nums1 < nums2;
        }
    }
}

你可能感兴趣的:(算法题)