【剑指Offer】俯视50题之31 - 40题
面試題31連續子數組的最大和?
面試題32從1到n整數中1出現的次數?
面試題33把數組排成最小的數?
面試題34丑數?
面試題35第一個僅僅出現一次的字符?
面試題36數組中的逆序對
面試題37兩個鏈表的第一個公共結點?
面試題38數字在排序數組中出現的次數?
面試題39二叉樹的深度?面試題40數組中僅僅出現一次的數字?
/*******************************************************/
面試題31連續子數組的最大和?,輸入一個數組。數組里面有正數,也有負數。
求連續數的最大值
實現例如以下:
int MaxSum(int num[], int length) {int CurrentSum = 0;int iResult = 0x80000000;if (num == NULL || length < 0){return 0;/* invalid */}for (int i = 0; i < length; i++){if (CurrentSum <= 0){CurrentSum = num[i];}else{CurrentSum += num[i];}if (CurrentSum > iResult)iResult = CurrentSum;}return iResult; }面試題32從1到n整數中1出現的次數?,輸入一個N,求1到N全部的整數中1出現的次數
實現例如以下:
#include <iostream>int CountNum(int n) {int iCurrentNum = 0;/* 當前位的數 */int iNTemp = n;int iResult = 0;int iBase = 1; /* 個位 */int iRemain = 0;if (n <= 0){return 0;}while (iNTemp > 0){iCurrentNum = iNTemp % 10;iNTemp = iNTemp/10;if (iCurrentNum > 1){iResult+= (iNTemp + 1)*iBase;}else if (iCurrentNum == 1){iResult+= (iNTemp)*iBase + iRemain + 1;}else if (iCurrentNum == 0){iResult+= (iNTemp)*iBase;}iRemain += iCurrentNum*iBase; /* 先計算剩余數大小*/iBase = iBase*10; /**然后計算下次base位*/ }return iResult; }int main() {printf("%d\n",CountNum(11)); }
面試題33把數組排成最小的數?
實現例如以下:
#include <iostream> #define MAX_NUM_LENGTH 10int compare(const void *str1, const void *str2) {char str1Temp[MAX_NUM_LENGTH*2 +1];char str2Temp[MAX_NUM_LENGTH*2 +1];strcpy(str1Temp, (const char*)str1);strcat(str1Temp, (const char*)str2);strcpy(str2Temp, (const char*)str2);strcat(str2Temp, (const char*)str1);return strcmp(str1Temp,str2Temp);} void GetMinNum(int num[], int length) {char **numStr = (char **)malloc(length + 1);for (int i = 0; i < length; i++){numStr[i] = (char *)malloc(MAX_NUM_LENGTH +1);sprintf(numStr[i],"%d",num[i]);}qsort(numStr,length,sizeof(char *),compare);for (int i = 0; i < length; i++){printf("%s",numStr[i]);}/* 釋放內存 */for (int i = 0; i < length; i++){free(numStr[i]);}free(numStr);}int main() {int num[] = {1,234,341};GetMinNum(num, 3); }
面試題34丑數?
實現例如以下:
#include <iostream> #define MAX_NUM_LENGTH 10int min(int a, int b, int c) {int min = (a>b)?b:a;min = (min > c)?
c:min; return min; } /* 僅僅能被2、3、5整除的 */ int GetUglyNum(int n) { /* 創建一個n個元素的數組 */ int UglyNum[n]; int p2 = 0; int p3 = 0; int p5 = 0; int NextIndex = 1; UglyNum[0] = 1; while(NextIndex < n) { UglyNum[NextIndex] = min(UglyNum[p2]*2, UglyNum[p3]*3 ,UglyNum[p5]*5); while(UglyNum[p2]*2 <= UglyNum[NextIndex]) { p2++; } while(UglyNum[p3]*3 <= UglyNum[NextIndex]) { p3++; } while(UglyNum[p5]*5 <= UglyNum[NextIndex]) { p5++; } NextIndex++; } return UglyNum[NextIndex - 1]; } int main() { printf("%d\n",GetUglyNum(3)); }
面試題35第一個僅僅出現一次的字符?
實現例如以下:
#include <iostream> #define VOS_OK 0 #define VOS_ERR 1/* 僅僅能被2、3、5整除的 */ int GetFirstChar(char *str, char *result) {unsigned int hashNum[256] = {0};char *p;if (str == NULL){return VOS_ERR;}p = str;while(*p != '\0'){hashNum[*p]++;p++;}p = str;while(*p!= '\0'){if (hashNum[*p] == 1){*result = *p;return VOS_OK;}p++;}return VOS_ERR;}int main() {char iChar;if (VOS_OK == GetFirstChar("aabcddb", &iChar)){printf("%c\n",iChar);}else{printf("Error!"); } }
面試題36數組中的逆序對
實現例如以下:
/* 求數組中的逆序對 */ #include <iostream> #define VOS_OK 0 #define VOS_ERR 1 int Merge(int *numA, int begin,int mid, int end) {int startA = begin;int startB = mid + 1;int *numB = (int *)malloc(sizeof(int)*(end + 1));int currentIndex = 0;long long result = 0;if (numA == NULL || begin > mid || mid > end)/* 其余異常函數調用處保證 */{return 0;}while (startA <=mid && startB <= end){if (numA[startA] <= numA[startB]){numB[currentIndex] = numA[startA++];}else{numB[currentIndex] = numA[startB++];/* 前面的大于后面的,則前數組之后的元素也大于該元素 */result += mid - startA + 1;}currentIndex++;}while (startA <= mid){numB[currentIndex++] = numA[startA++];}while (startB <= end){numB[currentIndex++] = numA[startB++];}for (int i = begin; i <= end; i++){numA[i] = numB[i];}free(numB);return result;}int MergeSort(int *num, int start, int end) {int result = 0;int mid;if (num == NULL || start >= end) /* 注意start == end 的時候*/{return 0; }mid = (start + end)>>1;result = MergeSort(num, start, mid) + MergeSort(num, mid +1, end);result += Merge(num,start,mid,end);return result;}int main() {int num[]={2,1,3,5,6};printf("%d\n",MergeSort(num, 0, 4)); }
面試題37兩個鏈表的第一個公共結點?
實現例如以下:
? 1)暴力法
? ? ? ? ?每次遍歷鏈表A,然后將鏈表A中當前結點在鏈表B中查找。假設找到則停止查找,返回。
? 2)空間換取時間
? ? ? ?將兩個鏈表都入棧,然后從最后一個結點開始比較。直到不相等為止。
? 3)同一時候向后查找
?? 先遍歷鏈表A得長度lengthA。再遍歷鏈表B得長度lengthB
?? 假如A比B長n。則A先走n步,假如B比A長n,則B先走n步。
?? 然后同一時候向后走,直到第一個相等的結點
面試題38數字在排序數組中出現的次數?
有兩種思路:利用二分查找法,找到該數中間出現的位置,然后分別向前后遍歷同樣數,可得到該數出現的次數
? ? ?利用二分查找法,找打該數最左邊及最右邊出現的位置。然后就能夠求得該數出現的次數
左右查詢實現例如以下:
#include <iostream> int MaxSum(int num[], int length, int value) {int iResult = 0;int i = 0;int j = length - 1;int mid;int k;while(i <= j ){mid = (i + j)>>1;if (num[mid] > value){j= mid - 1;}else if (num[mid] < value){i = mid + 1;}else{/* 向左查詢*/k = mid-1;while (k >= i &&(num[k] == value)){k--;iResult++;}/* 向右查詢*/k = mid+1;while (k <= j &&(num[k] == value)){ k++;iResult++;}printf("================");return iResult + 1;}}return iResult; }int main() {int num[]={2,2,2,2,5,5,6,6};printf("%d\n",MaxSum(num, 8, 2) );getchar(); }
第二種實現方法:
#include <iostream> int GetFirstK(int num[], int length, int value) {int mid;int i = 0;int j = length - 1;if (num == NULL){return 0;}while (i <= j){mid = (i + j)>>1;if (num[mid] > value){j = mid - 1;}else if (num[mid] < value){i = mid + 1;}else{if (mid -1 >= 0 && (num[mid - 1] == value)){j = mid - 1;}else{return mid;}}}return 0; }int GetLastK(int num[], int length, int value) {int mid;int i = 0;int j = length - 1;if (num == NULL){return 0;}while (i <= j){mid = (i + j)>>1;if (num[mid] > value){j = mid - 1;}else if (num[mid] < value){i = mid + 1;}else{if (mid + 1 <= j && (num[mid + 1] == value)){i = mid + 1;}else{return mid;}}}return 0; }int main() {int num[]={2,2,2,2,5,5,6,6};printf("%d\n",GetLastK(num, 8, 2) - GetFirstK(num, 8, 2) + 1);getchar(); }
面試題39二叉樹的深度?
實現例如以下:
int DepthTree(BinaryNode *root) {int leftDepth = 0;int rightDepth = 0;if (root == NULL){return 0;}leftDepth = DepthTree(root->lchild);rightDepth = DepthTree(root->rchild);retrun (leftDepth > rightDepth)? (leftDepth + 1):(rightDepth + 1); }
擴展題目:推斷一個樹是否是平衡二叉樹
實現例如以下:
bool IsBlanceTree(BinaryNode *root, int *depth) {int leftDepth = 0;int rightDepth = 0;int diff;if (root == NULL){return true;}leftDepth = DepthTree(root->lchild);rightDepth = DepthTree(root->rchild);if (IsBlanceTree(root->lchild, &leftDepth)&&IsBlanceTree(root->rchild, &rightDepth)){diff = leftDepth - rightDepth;if (diff < 1 && diff > -1){*depth = (leftDepth > rightDepth)? (leftDepth + 1):(rightDepth + 1);return true;}}retrun false; }
面試題40數組中僅僅出現一次的數字?:給一個數組,數組中有兩個數僅僅出現一次。其余數出現兩次,求這兩個數
思路:將數組分成兩組,分別異或去重。怎樣分組呢?分組依據異或之后。最后一位二進制值為1的位分組。對數組一進行異或最后得一個數。對數組二異或。最后得還有一個數。
則最后得到的兩個數是所求的數。
實現例如以下:
int FindFirstBitIsOne(int resultOR) {for (int i = 0; i < 32; i++){if (resultOR & (1 << i)){return i;}}return 0;}int IsBitOne(int data, int indexOfOne) {return data & (1<<indexOfOne);} void FindNumsAppearOnce(int data[],int length,int *num1,int num2) {if (data == NULL || length < 2){return;}int resultOR = 0;for (int i = 0; i < length; i++){resultOR ^=data[i];}int indexOfOne = FindFirstBitIsOne(resultOR);for (int j = 0; j < length; j++){if (IsBitOne(data[j], indexOfOne)){*num1 ^=data[j];}else{*num2^=data[j];}}}
posted on 2017-05-24 10:29 mthoutai 閱讀(...) 評論(...) 編輯 收藏
轉載于:https://www.cnblogs.com/mthoutai/p/6897666.html
總結
以上是生活随笔為你收集整理的【剑指Offer】俯视50题之31 - 40题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bootstrap table教程--使
- 下一篇: js模块化历程