<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>

          數(shù)組還能這么玩?

          共 36322字,需瀏覽 73分鐘

           ·

          2021-06-12 22:12

          關(guān)注、星標(biāo)公眾號(hào),直達(dá)精彩內(nèi)容

          來(lái)源:嵌入式大雜燴

          整理:李肖遙

          數(shù)組是最基本的數(shù)據(jù)結(jié)構(gòu),關(guān)于數(shù)組的面試題也屢見(jiàn)不鮮,本文羅列了一些常見(jiàn)的面試題,僅供參考。目前有以下18道題目。

          • 數(shù)組求和
          • 求數(shù)組的最大值和最小值
          • 求數(shù)組的最大值和次大值
          • 求數(shù)組中出現(xiàn)次數(shù)超過(guò)一半的元素
          • 求數(shù)組中元素的最短距離
          • 求兩個(gè)有序數(shù)組的共同元素
          • 求三個(gè)數(shù)組的共同元素
          • 找出數(shù)組中唯一的重復(fù)元素
          • 找出出現(xiàn)奇數(shù)次的元素
          • 求數(shù)組中滿(mǎn)足給定和的數(shù)對(duì)
          • 最大子段和
          • 最大子段積
          • 數(shù)組循環(huán)移位
          • 字符串逆序
          • 組合問(wèn)題
          • 合并兩個(gè)數(shù)組
          • 重排問(wèn)題
          • 找出絕對(duì)值最小的元素

          數(shù)組求和

          給定一個(gè)含有n個(gè)元素的整型數(shù)組a,求a中所有元素的和??赡苣鷷?huì)覺(jué)得很簡(jiǎn)單,是的,的確簡(jiǎn)單,但是為什么還要說(shuō)呢,原因有二,第一,這道題要求用遞歸法,只用一行代碼。第二,這是我人生中第一次面試時(shí)候遇到的題,意義特殊。

          分析

          簡(jiǎn)單說(shuō)一下,兩種情況

          1. 如果數(shù)組元素個(gè)數(shù)為0,那么和為0。

          2. 如果數(shù)組元素個(gè)數(shù)為n,那么先求出前n - 1個(gè)元素之和,再加上a[n - 1]即可

          代碼

          // 數(shù)組求和
          int sum(int*a, int n)
          {
             return n == 0 ? 0 : sum(a, n -1) + a[n -1];
          }

          求數(shù)組的最大值和最小值

          給定一個(gè)含有n個(gè)元素的整型數(shù)組a,找出其中的最大值和最小值

          分析

          常規(guī)的做法是遍歷一次,分別求出最大值和最小值,但我這里要說(shuō)的是分治法(Divide and couquer),將數(shù)組分成左右兩部分,先求出左半部份的最大值和最小值,再求出右半部份的最大值和最小值,然后綜合起來(lái)求總體的最大值及最小值。

          這是個(gè)遞歸過(guò)程,對(duì)于劃分后的左右兩部分,同樣重復(fù)這個(gè)過(guò)程,直到劃分區(qū)間內(nèi)只剩一個(gè)元素或者兩個(gè)元素。

          代碼

          // 求數(shù)組的最大值和最小值,返回值在maxValue和minValue
          void MaxandMin(int *a, int l, int r, int& maxValue, int& minValue)
          {
              if(l == r) // l與r之間只有一個(gè)元素
              {
                  maxValue = a[l] ;
                  minValue = a[l] ;
                  return ;
              }

              if(l + 1 == r) // l與r之間只有兩個(gè)元素
              {
                  if(a[l] >= a[r])
                  {
                      maxValue = a[l] ;
                      minValue = a[r] ;
                  }
                  else
                  {
                      maxValue = a[r] ;
                      minValue = a[l] ;
                  }
                  return ;
              }

              int m = (l + r) / 2 ; // 求中點(diǎn)

              int lmax ; // 左半部份最大值
              int lmin ; // 左半部份最小值
              MaxandMin(a, l, m, lmax, lmin) ; // 遞歸計(jì)算左半部份

              int rmax ; // 右半部份最大值
              int rmin ; // 右半部份最小值
              MaxandMin(a, m + 1, r, rmax, rmin) ; // 遞歸計(jì)算右半部份

              maxValue = max(lmax, rmax) ; // 總的最大值
              minValue = min(lmin, rmin) ; // 總的最小值
          }

          求數(shù)組的最大值和次大值

          給定一個(gè)含有n個(gè)元素的整型數(shù)組,求其最大值和次大值

          分析

          思想和上一題類(lèi)似,同樣是用分治法,先求出左邊的最大值leftmax和次大值leftsecond,再求出右邊的最大值rightmax和次大值rightsecond,然后合并,如何合并呢?分情況考慮

          1 如果leftmax > rightmax,那么可以肯定leftmax是最大值,但次大值不一定是rightmax,但肯定不是rightsecond,只需將leftsecond與rightmax做一次比較即可。

          2 如果rightmax > leftmax,那么可以肯定rightmax是最大值,但次大值不一定是leftmax,但肯定不是leftsecond,所以只需將leftmax與rightsecond做一次比較即可。

          注意

          這種方法無(wú)法處理最大元素有多個(gè)的情況,比如3,5,7,7將返回7,7而不是7,5。感謝網(wǎng)友 從無(wú)到有靠誰(shuí)人 指出。

          代碼

          // 找出數(shù)組的最大值和次大值,a是待查找的數(shù)組,left和right是查找區(qū)間,max和second存放結(jié)果
          void MaxandMin(int a[], int left, int right, int&max, int&second)
          {
              if(left == right)
              {
                  max = a[left] ;
                  second =  INT_MIN;
              }
              elseif(left +1== right)
              {
                  max = a[left] > a[right] ? a[left] : a[right] ;
                  second = a[left] < a[right] ? a[left] : a[right] ;
              }
              else
              {
                  int mid = left + (right - left) /2 ;

                  int leftmax ;
                  int leftsecond ;
                  MaxandMin(a, left, mid, leftmax, leftsecond) ;

                  int rightmax ;
                  int rightsecond ;
                  MaxandMin(a, mid +1, right, rightmax, rightsecond) ;

                  if (leftmax > rightmax)
                  {
                      max = leftmax ;
                      second = leftsecond > rightmax ? leftsecond : rightmax ;
                  }
                  else
                  {
                      max = rightmax ;
                      second = leftmax < rightsecond ? rightsecond : leftmax ;
                  }
              }
          }

          求數(shù)組中出現(xiàn)次數(shù)超過(guò)一半的元素

          給定一個(gè)n個(gè)整型元素的數(shù)組a,其中有一個(gè)元素出現(xiàn)次數(shù)超過(guò)n / 2,求這個(gè)元素。據(jù)說(shuō)是百度的一道題

          分析

          設(shè)置一個(gè)當(dāng)前值和當(dāng)前值的計(jì)數(shù)器,初始化當(dāng)前值為數(shù)組首元素,計(jì)數(shù)器值為1,然后從第二個(gè)元素開(kāi)始遍歷整個(gè)數(shù)組,對(duì)于每個(gè)被遍歷到的值a[i]

          1 如果a[i]==currentValue,則計(jì)數(shù)器值加1

          2 如果a[i] != currentValue, 則計(jì)數(shù)器值減1,如果計(jì)數(shù)器值小于0,則更新當(dāng)前值為a[i],并將計(jì)數(shù)器值重置為1

          代碼

          // 找出數(shù)組中出現(xiàn)次數(shù)超過(guò)一半的元素
          int Find(int* a, int n)
          {
              int curValue = a[0] ;
              int count = 1 ;

              for (int i = 1; i < n; ++i)
              {
                  if (a[i] == curValue)
                      count++ ;
                  else
                  {
                      count-- ;
                      if (count < 0)
                      {
                          curValue = a[i] ;
                          count = 1 ;
                      }
                  }
              }

              return curValue ;
          }

          另一個(gè)方法是先對(duì)數(shù)組排序,然后取中間元素即可,因?yàn)槿绻硞€(gè)元素的個(gè)數(shù)超過(guò)一半,那么數(shù)組排序后該元素必定占據(jù)數(shù)組的中間位置。

          求數(shù)組中元素的最短距離

          給定一個(gè)含有n個(gè)元素的整型數(shù)組,找出數(shù)組中的兩個(gè)元素x和y使得abs(x - y)值最小

          分析

          先對(duì)數(shù)組排序,然后遍歷一次即可

          代碼

          int compare(const void* a, const void* b)
          {
              return *(int*)a - *(int*)b ;
          }

          // 求數(shù)組中元素的最短距離
          void MinimumDistance(int* a, int n)
          {
              // Sort
              qsort(a, n, sizeof(int), compare) ;

              int i ; // Index of number 1
              int j ; // Index of number 2

              int minDistance = numeric_limits<int>::max() ;
              for (int k = 0; k < n - 1; ++k)
              {
                  if (a[k + 1] - a[k] < minDistance)
                  {
                      minDistance = a[k + 1] - a[k] ;
                      i = a[k] ;
                      j = a[k + 1] ;
                  }
              }

              cout << "Minimum distance is: " << minDistance << endl ;
              cout << "i = " << i << " j = " << j << endl ;
          }

          求兩個(gè)有序數(shù)組的共同元素

          給定兩個(gè)含有n個(gè)元素的有序(非降序)整型數(shù)組a和b,求出其共同元素,比如

          a = 0, 1, 2, 3, 4

          b = 1, 3, 5, 7, 9

          輸出 1, 3

          分析

          充分利用數(shù)組有序的性質(zhì),用兩個(gè)指針i和j分別指向a和b,比較a[i]和b[j],根據(jù)比較結(jié)果移動(dòng)指針,則有如下三種情況

          1. a[i] < b[j],則i增加1,繼續(xù)比較

          2. a[i] == b[j],則i和j皆加1,繼續(xù)比較

          3. a[i] < b[j],則j加1,繼續(xù)比較

          重復(fù)以上過(guò)程直到i或j到達(dá)數(shù)組末尾。

          代碼

          // 找出兩個(gè)數(shù)組的共同元素
          void FindCommon(int* a, int* b, int n)
          {
              int i = 0;
              int j = 0 ;

              while (i < n && j < n)
              {
                  if (a[i] < b[j])
                      ++i ;
                  else if(a[i] == b[j])
                  {
                      cout << a[i] << endl ;
                      ++i ;
                      ++j ;
                  }
                  else// a[i] > b[j]
                      ++j ;
              }
          }

          這到題還有其他的解法,比如對(duì)于a中任意一個(gè)元素,在b中對(duì)其進(jìn)行Binary Search,因?yàn)閍中有n個(gè)元素,而在b中進(jìn)行Binary Search需要logn。所以找出全部相同元素的時(shí)間復(fù)雜度是O(nlogn)。

          另外,上面的方法,只要b有序即可,a是否有序無(wú)所謂,因?yàn)槲覀冎皇窃赽中做Binary Search。

          如果a也有序的話,那么再用上面的方法就有點(diǎn)慢了,因?yàn)槿绻鸻中某個(gè)元素在b中的位置是k的話,那么a中下一個(gè)元素在b中的位置一定位于k的右側(cè),所以本次的搜索空間可以根據(jù)上次的搜索結(jié)果縮小,而不是仍然在整個(gè)b中搜索。也即如果a和b都有序的話,代碼可以做如下修改,記錄上次搜索時(shí)b中元素的位置,作為下一次搜索的起始點(diǎn)。

          求三個(gè)數(shù)組的共同元素

          給定三個(gè)含有n個(gè)元素的整型數(shù)組a,b和c,求他們最小的共同元素。

          分析

          如果三個(gè)數(shù)組都有序,那么可以設(shè)置三個(gè)指針指向三個(gè)數(shù)組的頭部,然后根據(jù)這三個(gè)指針?biāo)傅闹颠M(jìn)行比較來(lái)移動(dòng)指針,直道找到共同元素。

          代碼

          // 三個(gè)數(shù)組的共同元素-只找最小的
          void FindCommonElements(int a[], int b[], int c[], int x, int y, int z)
          {
              for(int i = 0, j = 0, k = 0; i < x && j < y && k < z;)
              {
                  if(a[i] < b[j])
                  {
                      i++ ;
                  }
                  else // a[i] >= b[j]
                  {
                      if(b[j] < c[k])
                      {
                          j++ ;
                      }
                      else // b[j] >= c[k]
                      {
                          if(c[k] < a[i])
                          {
                              k++ ;
                          }
                          else // c[k] >= a[i]
                          {
                              cout << c[k] << endl ;
                              return ;
                          }
                      }
                  }
              }

              cout << "Not found!" << endl ;
          }

          如果三個(gè)數(shù)組都無(wú)序,可以先對(duì)a, b進(jìn)行排序,然后對(duì)c中任意一個(gè)元素都在b和c中做二分搜索。

          代碼

          // 找出三個(gè)數(shù)組的共同元素
          // O(NlogN)
          int UniqueCommonItem(int *a, int *b, int *c, int n)
          {
              // sort array a
              qsort(a, n, sizeof(int), compare) ; // NlogN

              // sort array b
              qsort(b, n, sizeof(int), compare) ; // NlogN

              // for each element in array c, do a binary search in a and b
              // This is up to a complexity of N*2*logN
              for (int i = 0; i < n; i++)
              {
                  if(BinarySearch(a, n, c[i]) && BinarySearch(b, n, c[i]))
                      return c[i] ;
              }

              return - 1 ; // not found
          }

          也可以對(duì)a進(jìn)行排序,然后對(duì)于b和c中任意一個(gè)元素都在a中進(jìn)行二分搜索,但是這樣做是有問(wèn)題的,你看出來(lái)了么?感謝網(wǎng)友yy_5533指正。

          代碼

          // 找出三個(gè)數(shù)組唯一的共同元素
          // O(NlogN)
          int UniqueCommonItem1(int *a, int *b, int *c, int n)
          {
              // sort array a
              qsort(a, n, sizeof(int), compare) ; // NlogN

              // Space for time
              bool *bb = new bool[n] ;
              memset(bb, 0, n) ;

              bool *bc = new bool[n] ;
              memset(bb, 0, n) ;

              // for each element in b, do a BS in a and mark all the common element
              for (int i = 0; i < n; i++) // NlogN
              {
                  if(BinarySearch(a, n, b[i]))
                      bb[i] = true ;
              }

              // for each element in c, do a BS only if b[i] is true
              for (int i = 0; i < n; i++) // NlogN
              {
                  if(b[i] && BinarySearch(a, n, c[i]))
                      return c[i] ;
              }

              return - 1 ; // not found
          }

          排序和二分搜索代碼如下

          // Determine whether a contains value k
          bool BinarySearch(int *a, int n, int k)
          {
              int left = 0 ;
              int right = n - 1 ;
              while (left <= right)
              {
                  int mid = (left + right) ;

                  if(a[mid] < k)
                      left = mid + 1 ;
                  if(a[mid] == k)
                      return true ;
                  else
                      right = mid - 1 ;
              }

              return false ;
          }

          // Compare function for qsort
          int compare(const void* a, const void* b)
          {
              return *(int*)a - *(int*)b ;
          }

          小小總結(jié)一下,對(duì)于在數(shù)組中進(jìn)行查找的問(wèn)題,可以分如下兩種情況處理

          1. 如果給定的數(shù)組有序,那么首先應(yīng)該想到Binary Search,所需O(logn)

          2. 如果給定的數(shù)組無(wú)序,那么首先應(yīng)該想到對(duì)數(shù)組進(jìn)行排序,很多排序算法都能在O(nlogn)時(shí)間內(nèi)對(duì)數(shù)組進(jìn)行排序,然后再使用二分搜索,總的時(shí)間復(fù)雜度仍是O(nlogn)。

          如果能做到以上兩點(diǎn),大多數(shù)關(guān)于數(shù)組的查找問(wèn)題,都能迎刃而解。

          找出數(shù)組中唯一的重復(fù)元素

          給定含有1001個(gè)元素的數(shù)組,其中存放了1-1000之內(nèi)的整數(shù),只有一個(gè)整數(shù)是重復(fù)的,請(qǐng)找出這個(gè)數(shù)

          分析

          求出整個(gè)數(shù)組的和,再減去1-1000的和

          代碼

          找出出現(xiàn)奇數(shù)次的元素

          給定一個(gè)含有n個(gè)元素的整型數(shù)組a,其中只有一個(gè)元素出現(xiàn)奇數(shù)次,找出這個(gè)元素。這道題實(shí)際上是一個(gè)變種,原題是找出數(shù)組中唯一一個(gè)出現(xiàn)一次的元素,下面的方法可以同時(shí)解決這兩道提。所以題目就用這個(gè)廣義的吧。

          分析

          因?yàn)閷?duì)于任意一個(gè)數(shù)k,有k ^ k = 0,k ^ 0 = k,所以將a中所有元素進(jìn)行異或,那么個(gè)數(shù)為偶數(shù)的元素異或后都變成了0,只留下了個(gè)數(shù)為奇數(shù)的那個(gè)元素。

          代碼

          int FindElementWithOddCount(int*a, int n)
          {
             int r = a[0] ;

             for (int i =1; i < n; ++i)
             {
                r ^= a[i] ;
             }

             return r ;
          }

          求數(shù)組中滿(mǎn)足給定和的數(shù)對(duì)

          給定兩個(gè)有序整型數(shù)組a和b,各有n個(gè)元素,求兩個(gè)數(shù)組中滿(mǎn)足給定和的數(shù)對(duì),即對(duì)a中元素i和b中元素j,滿(mǎn)足i + j = d(d已知)

          分析

          兩個(gè)指針i和j分別指向數(shù)組的首尾,然后從兩端同時(shí)向中間遍歷。

          代碼

          // 找出滿(mǎn)足給定和的數(shù)對(duì)
          void FixedSum(int* a, int* b, int n, int d)
          {
              for (int i = 0, j = n - 1; i < n && j >= 0)
              {
                  if (a[i] + b[j] < d)
                      ++i ;
                  else if (a[i] + b[j] == d)
                  {
                      cout << a[i] << ", " << b[j] << endl ;
                      ++i ;
                      --j ;
                  }
                  else // a[i] + b[j] > d
                      --j ;
              }
          }

          最大子段和

          給定一個(gè)整型數(shù)組a,求出最大連續(xù)子段之和,如果和為負(fù)數(shù),則按0計(jì)算,比如1, 2, -5, 6, 8則輸出6 + 8 = 14

          分析

          編程珠璣上的經(jīng)典題目,不多說(shuō)了。

          代碼

          // 子數(shù)組的最大和
          int Sum(int* a, int n)
          {
              int curSum = 0;
              int maxSum = 0;
              for (int i = 0; i < n; i++)
              {
                  if (curSum + a[i] < 0)
                      curSum = 0;
                  else
                  {
                      curSum += a[i] ;
                      maxSum = max(maxSum, curSum);
                  }
              }
              return maxSum;
          }

          最大子段積

          給定一個(gè)整型數(shù)組a,求出最大連續(xù)子段的乘積,比如 1, 2, -8, 12, 7則輸出12 * 7 = 84

          分析

          與最大子段和類(lèi)似,注意處理負(fù)數(shù)的情況

          代碼

          // 子數(shù)組的最大乘積
          int MaxProduct(int *a, int n)
          {
              int maxProduct = 1// max positive product at current position
              int minProduct = 1// min negative product at current position
              int r = 1// result, max multiplication totally

              for (int i = 0; i < n; i++)
              {
                  if (a[i] > 0)
                  {
                      maxProduct *= a[i];
                      minProduct = min(minProduct * a[i], 1);
                  }
                  else if (a[i] == 0)
                  {
                      maxProduct = 1;
                      minProduct = 1;
                  }
                  else // a[i] < 0
                  {
                      int temp = maxProduct;
                      maxProduct = max(minProduct * a[i], 1);
                      minProduct = temp * a[i];
                  }

                  r = max(r, maxProduct);
              }

              return r;
          }

          數(shù)組循環(huán)移位

          將一個(gè)含有n個(gè)元素的數(shù)組向右循環(huán)移動(dòng)k位,要求時(shí)間復(fù)雜度是O(n),且只能使用兩個(gè)額外的變量,這是在微軟的編程之美上看到的一道題

          分析

          比如數(shù)組 1 2 3 4循環(huán)右移1位 將變成 4 1 2 3, 觀察可知1 2 3 的順序在移位前后沒(méi)有改變,只是和4的位置交換了一下,所以等同于1 2 3 4 先劃分為兩部分

          1 2 3 | 4,然后將1 2 3逆序,再將4 逆序 得到 3 2 1 4,最后整體逆序 得到 4 1 2 3

          代碼

          // 將buffer中start和end之間的元素逆序
          void Reverseint buffer[], int start, int end )
          {
              while ( start < end )
              {
                  int temp = buffer[ start ] ;
                  buffer[ start++ ] = buffer[ end ] ;
                  buffer[ end-- ] = temp ;
              }
          }

          // 將含有n個(gè)元素的數(shù)組buffer右移k位
          void Shiftint buffer[], int n, int k )
          {
              k %= n ;

              Reverse( buffer, 0, n - k - 1) ;
              Reverse( buffer, n - k, n - 1 ) ;
              Reverse( buffer, 0, n - 1 ) ;
          }

          稍微擴(kuò)展一下,如果允許分配額外的數(shù)組,那么定義一個(gè)新的數(shù)組,然后將移位后的元素直接存入即可,也可以使用隊(duì)列,將移動(dòng)后得元素出對(duì),再插入隊(duì)尾即可.

          字符串逆序

          給定一個(gè)含有n個(gè)元素的字符數(shù)組a,將其原地逆序。

          分析

          可能您覺(jué)得這不是關(guān)于數(shù)組的,而是關(guān)于字符串的。是的。但是別忘了題目要求的是原地逆序,也就是不允許額外分配空間,那么參數(shù)肯定是字符數(shù)組形式,因?yàn)樽址遣荒鼙恍薷牡模ㄟ@里只C/C++中的字符串常量)。

          所以,和數(shù)組有關(guān)了吧,只不過(guò)不是整型數(shù)組,而是字符數(shù)組。用兩個(gè)指針?lè)謩e指向字符數(shù)組的首位,交換其對(duì)應(yīng)的字符,然后兩個(gè)指針?lè)謩e向數(shù)組中央移動(dòng),直到交叉。

          代碼

          // 字符串逆序
          void Reverse(char*a, int n)
          {
             int left =0;
             int right = n -1;

             while (left < right)
             {
               char temp = a[left] ;
               a[left++] = a[right] ;
               a[right--] = temp ;
             }
          }

          組合問(wèn)題

          給定一個(gè)含有n個(gè)元素的整型數(shù)組a,從中任取m個(gè)元素,求所有組合。比如下面的例子

          a = 1, 2, 3, 4, 5

          m = 3

          輸出

          1 2 3, 1 2 4, 1 2 5, 1 3 4, 1 3 5, 1 4 5

          2 3 4, 2 3 5, 2 4 5
          3 4 5

          分析

          典型的排列組合問(wèn)題,首選回溯法,為了簡(jiǎn)化問(wèn)題,我們將a中n個(gè)元素值分別設(shè)置為1-n

          代碼

          // n選m的所有組合
          int buffer[100] ;

          void PrintArray(int *a, int n)
          {
              for (int i = 0; i < n; ++i)
                  cout << a[i] << "";
              cout << endl ;
          }

          bool IsValid(int lastIndex, int value)
          {
              for (int i = 0; i < lastIndex; i++)
              {
                  if (buffer[i] >= value)
                      return false;
              }
              return true;
          }

          void Select(int t, int n, int m)
          {
              if (t == m)
                  PrintArray(buffer, m);
              else
              {
                  for (int i = 1; i <= n; i++)
                  {
                      buffer[t] = i;
                      if (IsValid(t, i))
                          Select(t + 1, n, m);
                  }
              }
          }

          合并兩個(gè)數(shù)組

          給定含有n個(gè)元素的兩個(gè)有序(非降序)整型數(shù)組a和b。合并兩個(gè)數(shù)組中的元素到整型數(shù)組c,要求去除重復(fù)元素并保持c有序(非降序)。例子如下

          a = 1, 2, 4, 8

          b = 1, 3, 5, 8

          c = 1, 2, 3, 4, 5, 8

          分析

          利用合并排序的思想,兩個(gè)指針i,j和k分別指向數(shù)組a和b,然后比較兩個(gè)指針對(duì)應(yīng)元素的大小,有以下三種情況

          1. a[i] < b[j],則c[k] = a[i]。

          2. a[i] == b[j],則c[k]等于a[i]或b[j]皆可。

          3. a[i] > b[j],則c[k] = b[j]。

          重復(fù)以上過(guò)程,直到i或者j到達(dá)數(shù)組末尾,然后將剩下的元素直接copy到數(shù)組c中即可

          代碼

          // 合并兩個(gè)有序數(shù)組
          void Merge(int *a, int *b, int *c, int n)
          {
              int i = 0 ;
              int j = 0 ;
              int k = 0 ;

              while (i < n && j < n)
              {
                  if (a[i] < b[j])// 如果a的元素小,則插入a中元素到c
                  {
                      c[k++] = a[i] ;
                      ++i ;
                  }
                  else if (a[i] == b[j])// 如果a和b元素相等,則插入二者皆可,這里插入a
                  {
                      c[k++] = a[i] ;
                      ++i ;
                      ++j ;
                  }
                  else // a[i] > b[j] // 如果b中元素小,則插入b中元素到c
                  {
                      c[k++] = b[j] ;
                      ++j ;
                  }
              }

              if (i == n) // 若a遍歷完畢,處理b中剩下的元素
              {
                  for (int m = j; m < n; ++m)
                      c[k++] = b[m] ;
              }
              else//j == n, 若b遍歷完畢,處理a中剩下的元素
              {
                  for (int m = i; m < n; ++m)
                      c[k++] = a[m] ;
              }
          }

          重排問(wèn)題

          給定含有n個(gè)元素的整型數(shù)組a,其中包括0元素和非0元素,對(duì)數(shù)組進(jìn)行排序,要求:

          1. 排序后所有0元素在前,所有非零元素在后,且非零元素排序前后相對(duì)位置不變

          2. 不能使用額外存儲(chǔ)空間

          例子如下

          輸入 0, 3, 0, 2, 1, 0, 0

          輸出 0, 0, 0, 0, 3, 2, 1

          分析

          此排序非傳統(tǒng)意義上的排序,因?yàn)樗笈判蚯昂蠓?元素的相對(duì)位置不變,或許叫做整理會(huì)更恰當(dāng)一些。我們可以從后向前遍歷整個(gè)數(shù)組,遇到某個(gè)位置i上的元素是非0元素時(shí),如果a[k]為0,則將a[i]賦值給a[k],a[k]賦值為0。實(shí)際上i是非0元素的下標(biāo),而k是0元素的下標(biāo)

          代碼

          void Arrange(int* a, int n)
          {
              int k = n -1 ;
              for (int i = n -1; i >=0; --i)
              {
                  if (a[i] !=0)
                  {
                      if (a[k] ==0)
                      {
                          a[k] = a[i] ;
                          a[i] =0 ;
                      }
                      --k ;
                  }
              }
          }

          找出絕對(duì)值最小的元素

          給定一個(gè)有序整數(shù)序列(非遞減序),可能包含負(fù)數(shù),找出其中絕對(duì)值最小的元素,比如給定序列 -5, -3, -1, 2, 8 則返回1。

          分析

          由于給定序列是有序的,而這又是搜索問(wèn)題,所以首先想到二分搜索法,只不過(guò)這個(gè)二分法比普通的二分法稍微麻煩點(diǎn),可以分為下面幾種情況

          • 如果給定的序列中所有的數(shù)都是正數(shù),那么數(shù)組的第一個(gè)元素即是結(jié)果。
          • 如果給定的序列中所有的數(shù)都是負(fù)數(shù),那么數(shù)組的最后一個(gè)元素即是結(jié)果。
          • 如果給定的序列中既有正數(shù)又有負(fù)數(shù),那么絕對(duì)值得最小值一定出現(xiàn)在正數(shù)和負(fù)數(shù)的連接處。

          為什么?

          因?yàn)閷?duì)于負(fù)數(shù)序列來(lái)說(shuō),右側(cè)的數(shù)字比左側(cè)的數(shù)字絕對(duì)值小,如上面的-5, -3, -1, 而對(duì)于整整數(shù)來(lái)說(shuō),左邊的數(shù)字絕對(duì)值小,比如上面的2, 8,將這個(gè)思想用于二分搜索,可先判斷中間元素和兩側(cè)元素的符號(hào),然后根據(jù)符號(hào)決定搜索區(qū)間,逐步縮小搜索區(qū)間,直到只剩下兩個(gè)元素。

          代碼

          單獨(dú)設(shè)置一個(gè)函數(shù)用來(lái)判斷兩個(gè)整數(shù)的符號(hào)是否相同。

          bool SameSign(int a, int b)
          {
              if (a * b > 0)
                  return true;
              else
                  return false;
          }

          主函數(shù)代碼。

          // 找出一個(gè)非遞減序整數(shù)序列中絕對(duì)值最小的數(shù)
          int MinimumAbsoluteValue(int* a, int n)
          {
              // Only one number in array
              if (n ==1)
              {
                  return a[0] ;
              }

              // All numbers in array have the same sign
              if (SameSign(a[0], a[n -1]))
              {
                  return a[0] >=0? a[0] : a[n -1] ;
              }

              // Binary search
              int l =0 ;
              int r = n -1 ;

              while(l < r)
              {
                  if (l +1== r)
                  {
                      return abs(a[l]) < abs(a[r]) ? a[l] : a[r] ;
                  }

                  int m = (l + r) /2 ;

                  if (SameSign(a[m], a[r]))
                  {
                      r = m -1;
                      continue;
                  }
                  if (SameSign(a[l], a[m]))
                  {
                      l = m +1 ;
                      continue;
                  }
              }
          }

          這段代碼是有問(wèn)題的,感謝網(wǎng)友lingyunfish的指正,你看出來(lái)了么?修改后的代碼如下:

          // 找出一個(gè)非遞減序整數(shù)序列中絕對(duì)值最小的數(shù)
          int MinimumAbsoluteValue(int* a, int n)
          {
              // Only one number in array
              if (n ==1)
              {
                  return a[0] ;
              }

              // All numbers in array have the same sign
              if (SameSign(a[0], a[n -1]))
              {
                  return a[0] >=0? a[0] : a[n -1] ;
              }

              // Binary search
              int l =0 ;
              int r = n -1 ;

              while(l < r)
              {
                  if (l + 1 == r)
                  {
                      return abs(a[l]) < abs(a[r]) ? a[l] : a[r] ;
                  }

                  int m = (l + r) /2 ;

                  if (SameSign(a[m], a[r]))
                  {
                      r = m;
                      continue;
                  }
                  else
                  {
                      l = m ;
                      continue;
                  }
              }
          }

          版權(quán)聲明:本文來(lái)源網(wǎng)絡(luò),免費(fèi)傳達(dá)知識(shí),版權(quán)歸原作者所有。如涉及作品版權(quán)問(wèn)題,請(qǐng)聯(lián)系我進(jìn)行刪除。

          來(lái)源:https://www.cnblogs.com/graphics/archive/2010/08/24/1761620.html

          ????????????????  END  ????????????????

          推薦閱讀:


          嵌入式編程專(zhuān)輯
          Linux 學(xué)習(xí)專(zhuān)輯
          C/C++編程專(zhuān)輯
          Qt進(jìn)階學(xué)習(xí)專(zhuān)輯

          關(guān)注我的微信公眾號(hào),回復(fù)“加群”按規(guī)則加入技術(shù)交流群。


          點(diǎn)擊“閱讀原文”查看更多分享。

          瀏覽 35
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  seseav | 丁香五月 一区 | 麻豆国产一区二区三区四区 | 婷婷激情综合网 | 精品无码视频在线观看 |