<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          那些可以用快速排序秒殺的經(jīng)典題(一)

          共 5676字,需瀏覽 12分鐘

           ·

          2021-06-11 23:58

          天我們一起來看一下可以用快速排序秒殺的經(jīng)典題,或許這些題目大家已經(jīng)做過,不過可以再來一起復(fù)習(xí)一遍,加深印象。

          閱讀這篇文章之前,大家要先去看一下我之前寫過的一個快速排序?qū)懥丝?10000 字?,這樣才不會對這篇文章一知半解。好啦,我們一起開整吧。
          在上篇文章中,我們提到了,快速排序的優(yōu)化,利用三向切分來優(yōu)化數(shù)組中存在大量重復(fù)元素的情況,到了這里各位應(yīng)該猜到我想寫什么了吧,
          對滴,我們今天先來說一下那個非常經(jīng)典的荷蘭國旗問題。
          問題來源:
          https://www.jianshu.com/p/356604b8903f
          問題描述:
          荷蘭國旗是由紅白藍3種顏色的條紋拼接而成,如下圖所示:
          荷蘭國旗
          假設(shè)這樣的條紋有多條,且各種顏色的數(shù)量不一,并且隨機組成了一個新的圖形,新的圖形可能如下圖所示,但是絕非只有這一種情況:
          荷蘭國旗問題
          需求是:把這些條紋按照顏色排好,紅色的在上半部分,白色的在中間部分,藍色的在下半部分,我們把這類問題稱作荷蘭國旗問題
          我們把荷蘭國旗問題用數(shù)組的形式表達一下是這樣的:
          給定一個整數(shù)數(shù)組,給定一個值 K,這個值在原數(shù)組中一定存在,要求把數(shù)組中小于 K 的元素放到數(shù)組的左邊,大于K的元素放到數(shù)組的右邊,等于K的元素放到數(shù)組的中間。
          這不就是我們之前說過的三向切分嗎?一模一樣!
          那么 leetcode 有沒有相似問題呢?當(dāng)然有的,我們一起來看下面這道題
             leetcode 75 顏色分類
          題目描述:
          給定一個包含紅色、白色和藍色,一共 n 個元素的數(shù)組,原地對它們進行排序,使得相同顏色的元素相鄰,并按照紅色、白色、藍色順序排列。
          此題中,我們使用整數(shù) 0、 1 和 2 分別表示紅色、白色和藍色。
          示例 1:
          輸入:nums = [2,0,2,1,1,0]
          輸出:[0,0,1,1,2,2]
          示例 2:
          輸入:nums = [2,0,1]
          輸出:[0,1,2]
          示例 3:
          輸入:nums = [0]
          輸出:[0]
          示例 4:
          輸入:nums = [1]
          輸出:[1]
          解題思路
          這個題目我們使用 Arrays.sort() 解決,哈哈,但是那樣太無聊啦,題目含義就是讓我們將所有的 0 放在前面,2放在后面,1 放在中間,是不是和我們上面說的荷蘭國旗問題一樣。此時我們僅僅將 1 做為基準值。
          下面我們直接看代碼吧,和快速排序優(yōu)化三向切分代碼基本一致。
          class Solution {
              public void sortColors(int[] nums) {
                  int len = nums.length;
                  int left = 0;
                  //這里和三向切分不完全一致
                  int i = left;
                  int right = len-1;

                  while (i <= right) {
                       if (nums[i] == 2) {
                           swap(nums,i,right--);
                       } else if (nums[i] == 0) {
                           swap(nums,i++,left++);
                       } else {
                           i++;
                       }
                  }     
              }
              public void swap (int[] nums, int i, int j) {
                  int temp = nums[i];
                  nums[i] = nums[j];
                  nums[j] = temp;
              }
          }
          另外我們看這段代碼,有什么問題呢?那就是我們即使完全符合時,仍會交換元素,這樣會大大降低我們的效率。
          例如:[0,0,0,1,1,1,2,2,2]
          此時我們完全符合情況,不需要交換元素,但是按照我們上面的代碼,0,2 的每個元素會和自己進行交換,所以這里我們可以根據(jù)  i  和 left 的值是否相等來決定是否需要交換,大家可以自己寫一下。
          下面我們看一下另外一種寫法
          這個題目的關(guān)鍵點就是,當(dāng)我們 nums[i] 和 nums[right] 交換后,我們的 nums[right] 此時指向的元素是符合要求的,但是我們 nums[i] 指向的元素不一定符合要求,所以我們需要繼續(xù)判斷, nums[i] 是否還需要和 nums[left] 進行交換。
          細節(jié)地方
          我們 2 和 0 交換后,此時 i 指向 0 ,0 應(yīng)放在頭部,所以不符合情況,所以 0 和 1 仍需要交換。下面我們來看一下動畫來加深理解吧。

          代碼

          class Solution {
              public void sortColors(int[] nums) {

                  int left = 0;
                  int len = nums.length;
                  int right = len - 1;
                  for (int i = 0; i <= right; ++i) {
                      if (nums[i] == 0) {             
                          swap(nums,i,left);
                          left++;
                      }
                      if (nums[i] == 2) {
                          swap(nums,i,right);
                          right--;
                          //如果不等于 1 則需要繼續(xù)判斷,所以不移動 i 指針,i--
                          if (nums[i] != 1) {
                              i--;
                          }
                      }
                  }

              }
              public void swap (int[] nums,int i, int j) {
                  int temp = nums[i];
                  nums[i] = nums[j];
                  nums[j] = temp;
              }
          }
          好啦,這個問題到這就結(jié)束啦,是不是很簡單啊。
          瀏覽 73
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一级国产欧美成人A片 | 欧美性猛交XXXXX水多 | 日本天天艹人人艹视频在线观看 | 国产特级毛片A片WWW | 日本三级乱伦视频 |