本文介紹了有關數組的算法第一部分的Java
代碼實現,全部代碼都可經過 在線編譯器 直接運行,算法目錄:java
在一個二維數組中,每一行都按照 從左到右遞增的順序,每一列都按照 從上到下遞增的順序 排序,編寫一個函數,輸入這樣的一個二維數組和一個整數,判斷該整數是否在二位數組中。算法
首先要肯定整數存在於數組的一個 前提條件:若是最小的元素(左上角)大於d
,或者最大的元素(右下角)小於d
,那麼能夠肯定矩陣中不存在d
。數組
這裏須要關注一個特殊的點,二維數組右上角的元素d
,若是以d
所在的列將數組分爲左右兩個部分,那麼 右邊部分的全部元素都是大於d
的;而若是以d
所在的行將數組分爲上下兩個部分,那麼 上半部分的全部元素都是小於d
的。利用這一特性,咱們 從數組的右上角 開始搜尋:函數
x
軸的反方向遍歷,從 右至左找到第一個不大於d
的元素。y
軸的正方向遍歷,從 上至下找到第一個不小於d
的元素p
不存在於數組中,反之則從第一步開始重複。class Untitled {
static Boolean searchMisInt(int p[][], int d, int maxx, int maxy){
int minx = 0; int miny = 0;
while(minx <= maxx && miny <= maxy){
//若是最小的元素(左上角)大於d,或者最大的元素(右下角)小於d,那麼能夠肯定矩陣中不存在p。
if (p[minx][miny] > d|| p[maxx][maxy] < d)
return false;
//若是右上角的元素和p直接相等,那麼直接返回。
if (d == p[minx][maxy]) {
return true;
}
//不斷縮小矩形的範圍。
while (p[minx][maxy] > d) //從右上角的第一個元素,從右往左,找到第一個不大於d的元素。
maxy -= 1;
while (p[minx][maxy] < d) //從右上角的第一個元素,從上到下,找到第一個不小於d的元素。
minx += 1;
}
return false;
}
public static void main(String[] args) {
int p[][] = { {1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
System.out.println("result=" + searchMisInt(p, 10, 3, 3));
}
}
複製代碼
>> result=true
複製代碼
把一個數組最開始的若干個元素搬到數組的末尾,稱爲數組的旋轉。如今輸入一個遞增序列的旋轉數組,輸出旋轉數組的最小值,例如{1, 2, 3, 4, 5}
的一個旋轉數組爲{3, 4, 5, 1, 2}
,最小值爲1
。spa
加入通過旋轉後的數組不等於它自己,那麼這個旋轉後的數組有一個特色:它以最小值做爲分界點被分爲兩個部分,不包含最小值的前半部分是有序的,包含最小值的後半部分也是有序的,所以咱們能夠藉助 二分查找 的思想。code
首先得到當前數組的中點位置pMid
:排序
pMid
的數值 大於等於 首節點pStart
的數值,那麼說明 pMid 位於前半部分數組中,所以能夠肯定最小值在[pMid, pEnd]
之間pMid
的數值 小於等於 末節點pEnd
的數值,那麼說明 pMid 位於後半數組當中,而pMid
是[pMid,pEnd]
之間最小的元素,所以能夠肯定最小值在[pStart, pMid]
之間。class Untitled {
static int rotateMinIndex(int p[], int length){
if (length == 1) {
return 0;
}
int pStart = 0;
int pMid = 0;
int pEnd = length-1;
if (p[pStart] < p[pEnd]) {
return pStart;
}
while (pStart < pEnd - 1) {
pMid = (pStart + pEnd) >> 1;
if (p[pStart] == p[pMid] && p[pMid] == p[pEnd])
return rotateMinIndexOrder(p, pStart, pEnd);
if (p[pMid] >= p[pStart]) //左邊數組是有序的,最小點在右邊
pStart = pMid;
else if(p[pMid] <= p[pEnd]) //右邊數組是有序的,最小點在左邊
pEnd = pMid;
}
if (p[pStart] > p[pEnd])
return p[pEnd];
return -1;
}
static int rotateMinIndexOrder(int p[], int pStart, int pEnd){
for(int i = pStart; i < pEnd; i++){
if (p[i+1] < p[i])
return i+1;
}
return pEnd;
}
public static void main(String[] args) {
int p[] = {3, 4, 5, 1, 2};
System.out.println("result=" + rotateMinIndex(p, 5));
}
}
複製代碼
>> result=1
複製代碼
輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得全部奇數位於數組的前半部分,全部偶數位於數組的後半部分。get
經過兩個變量pStart
、pEnd
分別記錄從首節點和末節點開始掃描的下標,pStart
從首節點向末節點開始掃描,若是找到一個偶數,那麼中止掃描,讓pEnd
從末節點向首節點開始掃描,直到找到一個奇數,而後和pStart
所指向的偶數交換,這樣就能保證[0, pStart]
之間的都是奇數,而[pEnd, len-1]
之間的都是偶數。編譯器
完成交換後,再開始移動pStart
尋找下一個偶數,重複上面的操做,直到pStart
和pEnd
相遇,就能夠知足問題的要求了。string
class Untitled {
static void printArray(int p[]) {
for (int i = 0; i < p.length; i++) {
System.out.print(p[i] + ",");
}
}
static void reverseOddEven(int p[], int length){
int i = 0;
int j = length-1;
int t;
while (true) {
/*i指向數組length,或指向一個偶數*/
while (i < length && p[i] % 2 != 0)
i++;
/*j指向-1,j指向一個奇數,j的值小於i*/
while (j >= 0 && (p[j] % 2 == 0) && j >= i)
j--;
if (i > j)
break;
t = p[i]; p[i] = p[j]; p[j] = t;
}
}
public static void main(String[] args) {
int p[] = {3, 4, 5, 1, 2};
reverseOddEven(p, p.length);
printArray(p);
}
}
複製代碼
>> 3,1,5,4,2,
複製代碼
找出數組中出現次數超過一半的數字
將整個數組中的元素當作兩類:出現次數超過一半的數字 和 其他數字。利用一個輔助的變量time
和d
,初始時候將d
設爲p[0]
,time
設爲1
,開始從頭開始遍歷數組。
class Untitled {
static Boolean verifyMoreThanHalf(int p[], int data, int length){
int time = 0;
for (int i = 0; i < length; i++) {
if(p[i] == data)
time++;
}
if ((time << 1) >= length)
return true;
return false;
}
static void moreThanHalf(int p[], int length) {
//初始化
int d = p[0];
int time = 1;
//從第二個元素開始遍歷。
for (int i = 1; i < length; i++) {
if(time == 0){
d = p[i];
time = 1;
}else if(d == p[i])
time += 1;
else
time -= 1;
}
if (verifyMoreThanHalf(p, d, length)) {
System.out.println("出現次數超過一半的元素=" + d);
} else {
System.out.println("沒有次數超過一半的元素");
}
}
public static void main(String[] args) {
int p[] = {1, 2, 3, 2, 2, -1, 2, 2, 8, 2, 2};
moreThanHalf(p, p.length);
}
}
複製代碼
>> 出現次數超過一半的元素=2
複製代碼