[Leedcode] [JAVA] [912個の質問] [ソートアルゴリズム]

[問題の説明]

给你一个整数数组 nums,将该数组升序排列。
示例 1:
输入:nums = [5,2,3,1]
输出:[1,2,3,5]

[思考]の答え

1.挿入ソート(馴染み)

規則正しいアレイインサートデジタル、順序付けられた配列のより長い長さになるたびに、限られた操作の後、全体としてアレイを注文しました。

  • 最適化:「秩序配列の挿入デジタル」このステップは、「一時変数」の最初の使用に割り当てられた後、最終的には「適切な要素」の位置を空いたシフト、および「一時変数の後、徐々に交換するために使用することはできません空席に割り当て戦略」(すなわち、上記の画像を意味します)。時間コーディングない場合は慎重に、おそらく提案マルチ試運転、配列の値を変更します

時間の複雑さ:O(N ^ 2)空間計算量:O(1)

public class Solution {

    // 插入排序:稳定排序,在接近有序的情况下,表现优异

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        // 循环不变量:将 nums[i] 插入到区间 [0, i) 使之成为有序数组
        for (int i = 1; i < len; i++) {
            // 先暂存这个元素,然后之前元素逐个后移,留出空位
            int temp = nums[i];
            int j = i;
            // 注意边界 j > 0
            while (j > 0 && nums[j - 1] > temp) {
                nums[j] = nums[j - 1];
                j--;
            }
            nums[j] = temp;
        }
        return nums;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/
2.マージソート(フォーカス)

余分なスペースで、合流する2つの注文した配列が長くかつ秩序ある配列を取得します。
時間複雑:O(NlogN)スペースの複雑さ:O(N)

  • 最適化は、1:使用中の「セル間」「挿入ソート」、似たような操作を持っているJavaソースコード、「セル間」でのターンは、超長パラメータ、テストの決定に必要ですが、私はJDKのソースコードにはこちらをご覧;
  • 最適化2:自身が状況下で注文された「二つの配列には、統合は必要ありません。
  • 最適化3:使用して、暫定動作させるの完全な配列インデックスオフセットの計算を避けるために、破壊と消費の一時的な配列を作成しないように、「マージ2は、配列を命じました」。
  • 注:マージソート実現の、特別な注意を払う場合は、ソート<=と<、コードで指定されているの違いを非安定にこのアルゴリズムを実装しません。
public class Solution {
    // 归并排序

    /**
     * 列表大小等于或小于该大小,将优先于 mergeSort 使用插入排序
     */
    private static final int INSERTION_SORT_THRESHOLD = 7;

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        int[] temp = new int[len];
        mergeSort(nums, 0, len - 1, temp);
        return nums;
    }

    /**
     * 对数组 nums 的子区间 [left, right] 进行归并排序
     *
     * @param nums
     * @param left
     * @param right
     * @param temp  用于合并两个有序数组的辅助数组,全局使用一份,避免多次创建和销毁
     */
    private void mergeSort(int[] nums, int left, int right, int[] temp) {
        // 小区间使用插入排序
        if (right - left <= INSERTION_SORT_THRESHOLD) {
            insertionSort(nums, left, right);
            return;
        }

        int mid = left + (right - left) / 2;
        // Java 里有更优的写法,在 left 和 right 都是大整数时,即使溢出,结论依然正确
        // int mid = (left + right) >>> 1;

        mergeSort(nums, left, mid, temp);
        mergeSort(nums, mid + 1, right, temp);
        // 如果数组的这个子区间本身有序,无需合并
        if (nums[mid] <= nums[mid + 1]) {
            return;
        }
        mergeOfTwoSortedArray(nums, left, mid, right, temp);
    }

    /**
     * 对数组 arr 的子区间 [left, right] 使用插入排序
     *
     * @param arr   给定数组
     * @param left  左边界,能取到
     * @param right 右边界,能取到
     */
    private void insertionSort(int[] arr, int left, int right) {
        for (int i = left + 1; i <= right; i++) {
            int temp = arr[i];
            int j = i;
            while (j > left && arr[j - 1] > temp) {
                arr[j] = arr[j - 1];
                j--;
            }
            arr[j] = temp;
        }
    }

    /**
     * 合并两个有序数组:先把值复制到临时数组,再合并回去
     *
     * @param nums
     * @param left
     * @param mid   [left, mid] 有序,[mid + 1, right] 有序
     * @param right
     * @param temp  全局使用的临时数组
     */
    private void mergeOfTwoSortedArray(int[] nums, int left, int mid, int right, int[] temp) {
       //void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
        System.arraycopy(nums, left, temp, left, right + 1 - left);

        int i = left;
        int j = mid + 1;
//两条有序序列合并
        for (int k = left; k <= right; k++) {
//left     mid +1
//[1,1,2,3]  [5,6,7,8]  
 //边界 左边遍历完 右边还没开始 右边持续插入
            if (i == mid + 1) {
                nums[k] = temp[j];
//没能改变值 
                j++;
// [5,6,7,8]   [1,1,2,3]
//边界  右边遍历完 左边还没开始 左边持续插入
            } else if (j == right + 1) {
                nums[k] = temp[i];
                i++;
            } else if (temp[i] <= temp[j]) {
                // 注意写成 < 就丢失了稳定性(相同元素原来靠前的排序以后依然靠前)
                nums[k] = temp[i];
                i++;
            } else {
                // temp[i] > temp[j]
                nums[k] = temp[j];
                j++;
            }
        }
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

3.クイックソート(フォーカス)

クイックソートするたびにスケジュール要素は、(この要素は、その最終的な位置の滞在に滞在する必要があります)、そして再帰的に整然と配列されるまで、続行するためには、行の左の部分と右に行く、
外国チェーンの[写真ダンプが失敗し、発信局は(IMG-bH18YcEd-1585662450983)直接ダウンアップロードした写真を保存することが推奨され、セキュリティチェーン機構を有していてもよい( https://upload-images.jianshu.io/upload_images/17025746-9d7d9ff3a2826052.png?imageMogr2/auto -orient /ストリップ%7CimageView2 / 2 / ])/ 1240ワット

import java.util.Random;

public class Solution {

    // 快速排序 1:基本快速排序

    /**
     * 列表大小等于或小于该大小,将优先于 quickSort 使用插入排序
     */
    private static final int INSERTION_SORT_THRESHOLD = 7;

    private static final Random RANDOM = new Random();


    public int[] sortArray(int[] nums) {
        int len = nums.length;
        quickSort(nums, 0, len - 1);
        return nums;
    }

    private void quickSort(int[] nums, int left, int right) {
        // 小区间使用插入排序
        if (right - left <= INSERTION_SORT_THRESHOLD) {
            insertionSort(nums, left, right);
            return;
        }

        int pIndex = partition(nums, left, right);
        quickSort(nums, left, pIndex - 1);
        quickSort(nums, pIndex + 1, right);
    }

    /**
     * 对数组 nums 的子区间 [left, right] 使用插入排序
     *
     * @param nums  给定数组
     * @param left  左边界,能取到
     * @param right 右边界,能取到
     */
    private void insertionSort(int[] nums, int left, int right) {
        for (int i = left + 1; i <= right; i++) {
            int temp = nums[i];
            int j = i;
            while (j > left && nums[j - 1] > temp) {
                nums[j] = nums[j - 1];
                j--;
            }
            nums[j] = temp;
        }
    }

//版本 1:基本快排:把等于切分元素的所有元素分到了数组的同一侧,可能会造成递归树倾斜;
    private int partition(int[] nums, int left, int right) {
//避免有序数组 效率低下
////随机生成一个整数,这个整数的范围就是[0,right - left + 1)
        int randomIndex = RANDOM.nextInt(right - left + 1) + left;
        swap(nums, left, randomIndex);

        // 基准值
        int pivot = nums[left];
        int lt = left;
        // 循环不变量:
        // all in [left + 1, lt] < pivot
        // all in [lt + 1, i) >= pivot
        for (int i = left + 1; i <= right; i++) {
            if (nums[i] < pivot) {
                lt++;
                swap(nums, i, lt);
            }
        }
        swap(nums, left, lt);
        return lt;
    }
//版本 2:双指针快排:把等于切分元素的所有元素等概率地分到了数组的两侧,避免了递归树倾斜,递归树相对平衡;
 private int partition(int[] nums, int left, int right) {
        int randomIndex = left + RANDOM.nextInt(right - left + 1);
        swap(nums, randomIndex, left);

        int pivot = nums[left];
        int lt = left + 1;
        int gt = right;

        // 循环不变量:
        // all in [left + 1, lt) <= pivot
        // all in (gt, right] >= pivot
        while (true) {
            while (lt <= right && nums[lt] < pivot) {
                lt++;
            }

            while (gt > left && nums[gt] > pivot) {
                gt--;
            }

            if (lt > gt) {
                break;
            }

            // 细节:相等的元素通过交换,等概率分到数组的两边
            swap(nums, lt, gt);
            lt++;
            gt--;
        }
        swap(nums, left, gt);
        return gt;
    }


    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

バージョン3:3針クイックドレーン:スライス要素が押し込ま中間アレイのすべての要素と同じである多くのサブ要素および切断要素は等しい再帰間隔の場合に大幅に低減
クイックに-partition()マージ()

private void quickSort(int[] nums, int left, int right) {
      // 小区间使用插入排序
      if (right - left <= INSERTION_SORT_THRESHOLD) {
          insertionSort(nums, left, right);
          return;
      }

      int randomIndex = left + RANDOM.nextInt(right - left + 1);
      swap(nums, randomIndex, left);

      // 循环不变量:
      // all in [left + 1, lt] < pivot
      // all in [lt + 1, i) = pivot
      // all in [gt, right] > pivot
      int pivot = nums[left];
      int lt = left;
      int gt = right + 1;

      int i = left + 1;
      while (i < gt) {
          if (nums[i] < pivot) {
              lt++;
              swap(nums, i, lt);
              i++;
          } else if (nums[i] == pivot) {
              i++;
          } else {
              gt--;
              swap(nums, i, gt);
          }
      }
      swap(nums, left, lt);
      // 注意这里,大大减少了两侧分治的区间
      quickSort(nums, left, lt - 1);
      quickSort(nums, gt, right);
  }

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

4.ヒープソート(ヒープがソート個々の状況に基づいて、ヒープを把握することが重要です)

ヒープはソート「ヒープソート」ソート最適化、最大の要素「健康の警告」アプローチはセクションを、スケジュール、およびされていないことにより、(O(N)O(N)の複雑さ)を選択するための選択ソートの必要性に選択されていない置きますあなたはO(\ Nを記録)が最大の要素を選出O(logN個)の道を注文することができますので、「ヒープ」の構築の一部となる予定。

  • 参考「アルゴリズム」のヒープセクション
public class Solution {

   public int[] sortArray(int[] nums) {
       int len = nums.length;
       // 将数组整理成堆
       heapify(nums);

       // 循环不变量:区间 [0, i] 堆有序
       for (int i = len - 1; i >= 1; ) {
           // 把堆顶元素(当前最大)交换到数组末尾
           swap(nums, 0, i);
           // 逐步减少堆有序的部分
           i--;
           // 下标 0 位置下沉操作,使得区间 [0, i] 堆有序
           siftDown(nums, 0, i);
       }
       return nums;
   }

   /**
    * 将数组整理成堆(堆有序)
    *
    * @param nums
    */
   private void heapify(int[] nums) {
       int len = nums.length;
       // 只需要从 i = (len - 1) / 2 这个位置开始逐层下移
       for (int i = (len - 1) / 2; i >= 0; i--) {
           siftDown(nums, i, len - 1);
       }
   }

   /**
    * @param nums
    * @param k    当前下沉元素的下标
    * @param end  [0, end] 是 nums 的有效部分
    */
   private void siftDown(int[] nums, int k, int end) {
       while (2 * k + 1 <= end) {
           int j = 2 * k + 1;
           if (j + 1 <= end && nums[j + 1] > nums[j]) {
               j++;
           }
           if (nums[j] > nums[k]) {
               swap(nums, j, k);
           } else {
               break;
           }
           k = j;
       }
   }

   private void swap(int[] nums, int index1, int index2) {
       int temp = nums[index1];
       nums[index1] = nums[index2];
       nums[index2] = temp;
   }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

5.選択ソート

いくつかのステップの上に、予定外の大部分の先頭にそれぞれ予定外の交換部の最小部分を選択すると、配列全体をスケジュールすることができます。すなわち:最初のように最小を選択し、最小秒を選択し、。
時間複雑:O(N)スペースの複雑さ:O(1)

  // 选择排序:每一轮选择最小元素交换到未排定部分的开头
import java.util.Arrays;

public class Solution {

    // 选择排序:每一轮选择最小元素交换到未排定部分的开头

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        // 循环不变量:[0, i) 有序,且该区间里所有元素就是最终排定的样子
        for (int i = 0; i < len - 1; i++) {
            // 选择区间 [i, len - 1] 里最小的元素的索引,交换到下标 i
            int minIndex = i;
            for (int j = i + 1; j < len; j++) {
                if (nums[j] < nums[minIndex]) {
                    minIndex = j;
                }
            }
            swap(nums, i, minIndex);
        }
        return nums;
    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }

    public static void main(String[] args) {
        int[] nums = {5, 2, 3, 1};
        Solution solution = new Solution();
        int[] res = solution.sortArray(nums);
        System.out.println(Arrays.toString(res));
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/
並べ替え6.ヒル(より多くの時間を費やす理解することは推奨されません)

挿入ソートの最適化。挿入ソートで、番号は上の場合は後に小さく、それが為替の数倍の前に来ているだろう。このアプローチを改善するために、「ヒルソート」。標準は「挿入ソート」のとき挿入ソートを使用して間隔をおいて、最後に「間隔」は1になるまでは、配列の要素で、この時点では、すでに「ほとんど秩序」で
ソートまだ明確な結論のシェルの時間複雑範囲のみ

public class Solution {

    // 希尔排序

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        int h = 1;

        // 使用 Knuth 增量序列
        // 找增量的最大值
        while (3 * h + 1 < len) {
            h = 3 * h + 1;
        }

        while (h >= 1) {
            // insertion sort
            for (int i = h; i < len; i++) {
                insertionForDelta(nums, h, i);
            }
            h = h / 3;
        }
        return nums;
    }

    /**
     * 将 nums[i] 插入到对应分组的正确位置上,其实就是将原来 1 的部分改成 gap
     *
     * @param nums
     * @param gap
     * @param i
     */
    private void insertionForDelta(int[] nums, int gap, int i) {
        int temp = nums[i];
        int j = i;
        // 注意:这里 j >= deta 的原因
        while (j >= gap && nums[j - gap] > temp) {
            nums[j] = nums[j - gap];
            j -= gap;
        }
        nums[j] = temp;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

7.バブルソート(理解)

外部ループペアワイズ比較、各ラウンドの終了時に最大スルー毎に予定の配列に要素の一部ではありません

public class Solution {

    // 冒泡排序:超时

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        for (int i = len - 1; i >= 0; i--) {
            // 先默认数组是有序的,只要发生一次交换,就必须进行下一轮比较,
            // 如果在内层循环中,都没有执行一次交换操作,说明此时数组已经是升序数组
            boolean sorted = true;
            for (int j = 0; j < i; j++) {
                if (nums[j] > nums[j + 1]) {
                    swap(nums, j, j + 1);
                    sorted = false;
                }
            }
            if (sorted) {
                break;
            }
        }
        return nums;
    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/
8.カウントシング(こちら)

各値は、カウントに応じて大整然としたアレイ出力に次いで小さなカウントを行う現れます。
-安定性のアプローチを維持することである:割り当て前面に背面から元の入力アレイの割り当てのデータに応じてステップ2に戻って、接頭辞、およびアレイの各要素が格納されたインデックスを保持している場合、アレイに接頭辞、カウントを行うこと情報(ここでは、薄すぎると言う理解することは困難ではない、重要ではないそれを持っていません)。

著者:liweiwei1419
リンクします。https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

public class Solution {

    // 计数排序

    private static final int OFFSET = 50000;

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        // 由于 -50000 <= A[i] <= 50000
        // 因此"桶" 的大小为 50000 - (-50000) = 10_0000
        // 并且设置偏移 OFFSET = 50000,目的是让每一个数都能够大于等于 0
        // 这样就可以作为 count 数组的下标,查询这个数的计数
        int size = 10_0000;

        // 计数数组
        int[] count = new int[size];
        // 计算计数数组
        for (int num : nums) {
            count[num + OFFSET]++;
        }

        // 把 count 数组变成前缀和数组
        for (int i = 1; i < size; i++) {
            count[i] += count[i - 1];
        }

        // 先把原始数组赋值到一个临时数组里,然后回写数据
        int[] temp = new int[len];
        System.arraycopy(nums, 0, temp, 0, len);

        // 为了保证稳定性,从后向前赋值
        for (int i = len - 1; i >= 0; i--) {
            int index = count[temp[i] + OFFSET] - 1;
            nums[index] = temp[i];
            count[temp[i] + OFFSET]--;
        }
        return nums;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/
9.選択ソート(こちら)
  • キーワードに基づいて並べ替え、例えば、数値の並べ替え、ビット、10、百のキーワードです。日付順に並べ替えられたデータの場合:年、月、日、時、分、秒キーワードがあります
  • 「基数ソート、」「ソートカウント」を使用します
public class Solution {

    // 基数排序:低位优先

    private static final int OFFSET = 50000;

    public int[] sortArray(int[] nums) {
        int len = nums.length;

        // 预处理,让所有的数都大于等于 0,这样才可以使用基数排序
        for (int i = 0; i < len; i++) {
            nums[i] += OFFSET;
        }

        // 第 1 步:找出最大的数字
        int max = nums[0];
        for (int num : nums) {
            if (num > max) {
                max = num;
            }
        }

        // 第 2 步:计算出最大的数字有几位,这个数值决定了我们要将整个数组看几遍
        int maxLen = getMaxLen(max);

        // 计数排序需要使用的计数数组和临时数组
        int[] count = new int[10];
        int[] temp = new int[len];

        // 表征关键字的量:除数
        // 1 表示按照个位关键字排序
        // 10 表示按照十位关键字排序
        // 100 表示按照百位关键字排序
        // 1000 表示按照千位关键字排序
        int divisor = 1;
        // 有几位数,外层循环就得执行几次
        for (int i = 0; i < maxLen; i++) {

            // 每一步都使用计数排序,保证排序结果是稳定的
            // 这一步需要额外空间保存结果集,因此把结果保存在 temp 中
            countingSort(nums, temp, divisor, len, count);

            // 交换 nums 和 temp 的引用,下一轮还是按照 nums 做计数排序
            int[] t = nums;
            nums = temp;
            temp = t;

            // divisor 自增,表示采用低位优先的基数排序
            divisor *= 10;
        }

        int[] res = new int[len];
        for (int i = 0; i < len; i++) {
            res[i] = nums[i] - OFFSET;
        }
        return res;
    }

    private void countingSort(int[] nums, int[] res, int divisor, int len, int[] count) {
        // 1、计算计数数组
        for (int i = 0; i < len; i++) {
            // 计算数位上的数是几,先取个位,再十位、百位
            int remainder = (nums[i] / divisor) % 10;
            count[remainder]++;
        }

        // 2、变成前缀和数组
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }

        // 3、从后向前赋值
        for (int i = len - 1; i >= 0; i--) {
            int remainder = (nums[i] / divisor) % 10;
            int index = count[remainder] - 1;
            res[index] = nums[i];
            count[remainder]--;
        }

        // 4、count 数组需要设置为 0 ,以免干扰下一次排序使用
        for (int i = 0; i < 10; i++) {
            count[i] = 0;
        }
    }

    /**
     * 获取一个整数的最大位数
     *
     * @param num
     * @return
     */
    private int getMaxLen(int num) {
        int maxLen = 0;
        while (num > 0) {
            num /= 10;
            maxLen++;
        }
        return maxLen;
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

10.選択ソート(こちら)
ublic class Solution {

    // 桶排序
    // 1 <= A.length <= 10000
    // -50000 <= A[i] <= 50000

    // 10_0000

    private static final int OFFSET = 50000;

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        // 第 1 步:将数据转换为 [0, 10_0000] 区间里的数
        for (int i = 0; i < len; i++) {
            nums[i] += OFFSET;
        }

        // 第 2 步:观察数据,设置桶的个数
        // 步长:步长如果设置成 10 会超出内存限制
        int step = 1000;
        // 桶的个数
        int bucketLen = 10_0000 / step;

        int[][] temp = new int[bucketLen + 1][len];
        int[] next = new int[bucketLen + 1];

        // 第 3 步:分桶
        for (int num : nums) {
            int bucketIndex = num / step;
            temp[bucketIndex][next[bucketIndex]] = num;
            next[bucketIndex]++;
        }

        // 第 4 步:对于每个桶执行插入排序
        for (int i = 0; i < bucketLen + 1; i++) {
            insertionSort(temp[i], next[i] - 1);
        }

        // 第 5 步:从桶里依次取出来
        int[] res = new int[len];
        int index = 0;
        for (int i = 0; i < bucketLen + 1; i++) {
            int curLen = next[i];
            for (int j = 0; j < curLen; j++) {
                res[index] = temp[i][j] - OFFSET;
                index++;
            }
        }
        return res;
    }

    private void insertionSort(int[] arr, int endIndex) {
        for (int i = 1; i <= endIndex; i++) {
            int temp = arr[i];
            int j = i;
            while (j > 0 && arr[j - 1] > temp) {
                arr[j] = arr[j - 1];
                j--;
            }
            arr[j] = temp;
        }
    }
}

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

[概要]

。##### 1つのランキングアルゴリズムの概要
[チェーン外画像ダンプが失敗し、発信局は、直接ダウンアップロードした写真を保存することが推奨され、セキュリティチェーン機構を有していてもよい(IMG-1VAMavOi-1585662450986)( HTTPS://upload-images.jianshu .IO / upload_images / 17025746-64aa4a7d0e174744.png?imageMogr2 /オートオリエント/ストリップ%7CimageView2 / 2 /])/ 1240ワット

1.1挿入ソート

  • 時間の複雑さ:O(N ^ 2)空間計算量:O(1)
  • 長所:「ほとんど秩序」配列が好調で、特に、「short配列」の振る舞いもとても良いです。「short配列」の特性が予定されているので、その最終的な位置からのすべての要素があまりにも遠くはありません
  • アプリケーション:セル間内のタスクの並べ替えを行うときは、「挿入ソート」を使用して回すことができます

1.2マージソート

  • 時間の複雑さ:複雑さO(NlogN)スペース:O(N)
    -アルゴリズムのアイデア:アルゴリズムの分野における再帰、分割統治イデオロギー問題解決には、再帰の詳細を理解し、再帰的な考え方を学ぶ「マージソート」を書き込むことにより、非常に一般的ですパーティションの考え方に精通し、非常に良い学習教材です。
    -利点:「マージソート」、良いことよりも、「クイックソート」、それは余分なスペースを意味している、あなたが「安定ソート」を達成することができ、Javaはマージソート(TimSortのアップグレードバージョンを使用して、ある「オブジェクトの配列」、のためのタスクをソートしてここで紹介しません)。

1.3高速行

  • 時間複雑:O(NlogN)スペースの複雑さ:O(logN個)
  • アルゴリズムのアイデア:代わりに、パーティションの方法を使用してのこの問題に関する2つに分割する分割統治(分割統治の考え方)、および「マージソート」違う、「クイックソート」「ポイント」は「マージソート」にしたくないではありません脳、そのため、中に「一緒に」何も処理はありません。
    [画像のダンプはチェーンが失敗し、発信局は(IMG-BWOPzOP8-1585662450988)(https://upload-images.jianshu.io/upload_images/17025746-ad48df7591da38ac.png直接アップロードダウン画像を保存することが推奨され、セキュリティチェーン機構を有していてもよいです?imageMogr2 /オートオリエント/ストリップ%7CimageView2 / 2 / W / 1240)]
    -短所:クイックソート失われた安定性、あなたはクイックソートの安定が必要な場合は、特定の比較機能、「安定化」で呼ばれるプロセスを定義する必要がありますここでは行われません。
  • :(特定のテストケースのための欠点:配列または配列)マストランダム分割要素(ピボット)の逆の順序は、そうでない場合は、入力配列内にある逆の順序で配列又は配列順序付き同等のクイックソートは非常に遅くなります(バブルソートまたは「選択ソート」)へ。

1.4ヒープソート

  • 時間複雑:O(NlogN)スペースの複雑さ:O(1)
  • ヒープはソート最適化の選択ソートで、予定外の部分に「健康警告」アプローチによる最大の要素(O(N)の複雑さ)、および選出に必要なソートを選択し、「ヒープの並べ替えを、」スケジュールされていない部分を取りました「ヒープ」へのビルド、あなたは注文することができますので、O(logN個)最大の要素によって選出されます。
  • ヒープは多くの言語にもと命名された非常に興味深いデータ構造である「優先キュー。」これは、「ツリー」構造、同様のデータ構造ならびに「互いに素なセット」、「ツリーライン」等の配列に基づいています。「プライオリティキューは、」いいえ違い「普通のキュー」その上、その時点から、チームから優先度の高い順に、特別なキューです。最高の「優先キュー」を達成するために、「優先度キュー」配列を達成するために使用することができるので、それはまた、規則的な配列で達成することができるが、長い直鎖状構造のように、複雑性が高くなり、「木」構造の利点を持っているが、「ヒープであります。 "

1.5選択ソート

  • 時間の複雑さ:O(N ^ 2)空間計算量:O(1)
  • 長所:交換の最小数。
  • 1つのアルゴリズムのアイデア:貪欲アルゴリズム:すべての決定は、単に現在の、現在の最適な、大域的最適を見てください。注:このアイデアはすべての回では適用されません。
  • アルゴリズム2:あまり政治的イデオロギー:外側のループするたびに、スケジュールの要素、完全に解決されるまで、問題の規模が徐々に低下し、ある「大と小、小のの。」「政治的イデオロギーマイナス」の典型的なアルゴリズムを使用することは、有名な「バイナリ検索」です。

1.6シェルソート

  • 時間の複雑さ:明確ではありません

1.7バブルソート(理解)

  • 時間の複雑さ:O(N ^ 2)空間計算量:O(1)
  • 長所:トラバーサルの間に、早期検出アレイはソート終了、順序付けられているのではなく、入力されたデータが順序であっても、という「選択ソート」、「選択ソート:「バブルソート」つの特徴を持っています愚かなすべてのプロセスを経る「場所「まだに必要」。

選択ソートソート1.8 1.9 1.10選択ソートをカウント

  • 時間複雑:O(N)の最適化
  • 特長:数がこの数の決定自体のサイズによって決定された場所は、それが比較を必要としません。また、思考のハッシュと考えることができます。値は、アドレスをマッピングされました。
  • 特長:特定の追加スペースがソートのタスクを完了するために必要とされます
  • 短所:多くの、主な理由はこれら三つの分類の使用の適用場面は、入力配列の各要素は、合理的な範囲内にあることを確認する必要があります
  • 利点:安定したソート安定せず、として実装することができます
2.コードの仕様

2.1ループ不変(高速放電)
-サイクルの開始前に定義された「ループ不変」変数を保持し、サイクルは、サイクルの終了後、同じ性質まま、問題の本質は、人工機能の面で定義されています。
書き込み数、最初の交換又は最初++ループ不変と等しくされていないアルゴリズムの有効性を証明する根拠は、コンプライアンスループ不変性を確保するためのコードを記述することである」、それは、間違っている、特に明確では決してだろう私たちは、コード内のコメントとして書かれた「ループ不変」に準拠しています。
2.2「アルゴリズム4」コードスタイルが推奨されていません

  • コードはポスターを書かれている、と読みやすさ、拡張性を確保するために標準化された文言を使用して、個人的なスタイルのコードを回避しようとしてください。
    [チェーンが失敗したイメージのダンプ、発信局は、((IMG-ntkuZXCs-1585662450990)直接アップロードダウン画像を保存することが推奨され、セキュリティチェーン機構を有していてもよい https://upload-images.jianshu.io/upload_images/17025746-5aba0141df398096.png ?imageMogr2 /オートオリエント/ストリップ7CimageView2の%/ 2 / W / 1240である)]
    2.3最適化変数名
  • 略語が表すよりLTは小さい(厳密に)より少ないです。
  • GTの略語が1より(厳密に)より大きいを表すより大きい。
  • LEは(このコードは使用されない)以下を示す、以下で省略形です。
  • より大きい、等しい、または(このコードが使用されていない)で表さ等しいよりや略語のGe大きいです。
3.ソート成功したエントリ書かれたインタビューは、慌てる必要はありません
  public int[] sortArray(int[] nums) {
        Arrays.sort(nums);
        return nums;
    }
アムウェイのウェブサイト:

ダイナミックなプレゼンテーションのためのアルゴリズム

参考リンクします。https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

公開された22元の記事 ウォンの賞賛0 ビュー412

おすすめ

転載: blog.csdn.net/dadongwudi/article/details/105233093