《剑指offer》-- 调整数组顺序使奇数位于偶数前面、顺时针打印矩阵、数字在排序数组中出现的次数
一、調整數組順序使奇數位于偶數前面:
1、題目:
輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有的奇數位于數組的前半部分,所有的偶數位于數組的后半部分,并保證奇數和奇數,偶數和偶數之間的相對位置不變
2、解決思路:
如果題目中沒有要求偶數和偶數、奇數和奇數之間的相對位置不變,這道題就比較簡單,我們只需維護兩個指針:第一個指針pHead 初始化為數組的第一個元素,第二個指針pTail 初始化為數組的最后一個元素。根據題目要求:所有奇數位于數組的前半部分,偶數位于數組的后半部分;我們只需:
①使指針pHead 向后遍歷,直到指向的整數為偶數;
②使指針pTail 向前遍歷,直到指向的整數為奇數;
③交換指針pHead 和指針pTail 所指向的元素。
④在 pHead 和 pTail 相遇之前,pHead繼續向后遍歷,pTail繼續向前遍歷。
回歸本題:
(1)本題第一種解決方法:
用空間換時間的做法,new一個數組,從頭開始遍歷,遇到偶數保存進新數組,并且刪除原先的偶數,最后將偶數部分接在奇數部分之后。(在這里就不貼代碼了)
(2)本題第二種解決方法:
首先尋找第一個奇數,并將其放在0號位置。然后將第一個奇數之前的元素全部往后移一位。第二步,依次在第一個奇數之后的元素中尋找奇數,找到之后,移動到第1號位置,重復第二步的步驟。就可以保證原來的相對順序。
代碼實現:
public void reOrderArray(int [] array) {int firstIndex=0;//記錄第一個奇數的位置int lastIndex=0;//記錄排好序的奇數的最后一個位置for(int i=0;i<array.length;i++){if(array[i]%2==1){//找到第一個奇數int temp=array[i];int ti=i;for(;ti>0;ti--){array[ti]=array[ti-1];//將第一個奇數之前的所有元素往后移動一個位置}array[0]=temp;//將第一個奇數放到array[0]位置firstIndex=i;break;}}for(++firstIndex;firstIndex<array.length;firstIndex++){//依次尋找剩余的奇數if(array[firstIndex]%2==1){int temp=array[firstIndex];int tj=firstIndex;for(;tj>lastIndex;tj--){array[tj]=array[tj-1];}array[++lastIndex]=temp;}}}(3)本題第三種解決方法:
個人覺得第三種方式是比較好的一種。
從數組中尋找第一個偶數,每當找到前面的偶數和偶數后面的第一個奇數之后,那么把之間的部分(包括那個偶數)統一后移一位, 因為之間的都是偶數,這樣把提前保存起來的那個奇數放到前邊空出來的那一位。這樣相當于132457把5移動到2 4這兩個偶數的前面,1和5本來就是前后順序的。這樣堡整理調整之后的奇偶各自的相對順序不會變。
代碼實現:
public class Solution {public void reOrderArray(int [] array) {int jishuIndex=0;//偶數后面的第一個奇數的下標int oushuIndex=0;//偶數的下標int temp = 0;while(jishuIndex<array.length && oushuIndex < array.length){//尋找第一個偶數的位置while(oushuIndex<array.length){if(array[oushuIndex]%2==0){break;}oushuIndex++;}//尋找偶數后面的第一個奇數:jishuIndex=oushuIndex+1;while(jishuIndex<array.length){if(array[jishuIndex]%2!=0){temp=array[jishuIndex];break;}jishuIndex++;}//將奇數放到第一個偶數的位置,偶數都往后面移動一格if(jishuIndex<array.length){for(int i=jishuIndex;i>oushuIndex;i--){array[i]=array[i-1];}array[oushuIndex]=temp;}else{break;}}} }?
?
二、順時針打印矩陣:
1、題目:
輸入一個矩陣,按照從外向里以順時針的順序依次打印出每一個數字,例如,如果輸入如下4 X 4矩陣: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 則依次打印出數字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
2、解題思路:
參考這篇博客:https://blog.csdn.net/yanxiaolx/article/details/52254590。
由于題目是以從外圈到內圈的順序依次打印,在矩陣中標注一圈作為分析的目標。設矩陣的寬度為cols,而其高度為rows。選取左上角坐標為(startX, startY),右下角坐標為(endX, endY)的一個圈來分析。
由于endX和endY可以根據startX、startY以及columns、rows來求得,因此此時我們只需要引入startX和startY兩個變量。我們可以想象有一個循環,在每一次循環里我們從(startX, startY)出發按照順時針打印數字。
接著分析這個循環結束的條件。對一個5×5的矩陣而言,最后一圈只有一個數字,對應的坐標為(2, 2)。我們發現5 > 2 * 2。對一個6×6的矩陣而言,最后一圈有四個數字,對應的坐標仍然為(2, 2)。我們發現6 > 2 * 2依然成立。于是我們可以得出,讓循環繼續的條件是“cols > startX * 2 && rows > startY * 2”。
接下來我們分析如何按照順時針的順序打印一圈的數字。我們可以分四步來打印:第一步是從左到右打印一行,第二步是從上到下打印一列,第三步從右到左打印一行,最后一步是從下到上打印一列。也就是我們把打印一圈數字這個問題,分解成四個子問題。
值得注意的是,最后一圈可能退化成只有一行、只有一列、甚至只有一個數字,因此打印這樣的一圈就不需要四步了。
3、實現代碼:
import java.util.ArrayList; public class Solution {public ArrayList<Integer> printMatrix(int [][] matrix) {if(matrix==null)return null;ArrayList<Integer> arrayList=new ArrayList<Integer>();int start =0;while(matrix[0].length>start*2 && matrix.length>start*2){printOneCircle(arrayList,matrix,start);start++;}return arrayList;}public void printOneCircle(ArrayList<Integer> arrayList,int [][] array,int start){int columns=array[0].length;int rows=array.length;int endX=columns-1-start;int endY=rows-1-start;//從左到右打印一行,不需要判斷for(int i=start;i<=endX;i++){int number = array[start][i];arrayList.add(number);}//從上到下打印一列數據if(start<endY){for(int i=start+1;i<=endY;i++){int number = array[i][endX];arrayList.add(number);}}//從右到左打印一行數據if(start<endX && start<endY){for(int i=endX-1;i>=start;i--){int number = array[endY][i];arrayList.add(number);}}//從下到上打印一列if(start<endX && start <endY-1){for(int i= endY-1;i>=start+1;i--){int number= array[i][start];arrayList.add(number);}}} }?
?
三、數字在排序數組中出現的次數:
1、題目:
統計一個數字在排序數組中出現的次數。
2、解題思路:
因為array中都是整數,所以可以稍微變一下,不是搜索k的兩個位置,而是搜索k-0.5和k+0.5,這兩個數應該插入的位置,然后相減即可。
3、代碼實現:
public class Test2 {public int GetNumberOfK(int [] array , int k) {return biSearch(array,k+0.5)-biSearch(array,k-0.5);}private int biSearch(int[] array,double num){int start=0;int end=array.length-1;while(start<=end){int mid = (end-start)/2+start;if(array[mid]>num){end=mid-1;}else if(array[mid]<num){start=mid+1;}}return start;} }?
總結
以上是生活随笔為你收集整理的《剑指offer》-- 调整数组顺序使奇数位于偶数前面、顺时针打印矩阵、数字在排序数组中出现的次数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《剑指offer》-- 树的子结构、二叉
- 下一篇: 《剑指offer》-- 栈的压入与弹出序