劍指offer(41-68題)
P214
41.資料流中的中位數
class Solution { public: vector<int> maxHeap; vector<int> minHeap; void Insert(int num) { int minSize = minHeap.size(), maxSize = maxHeap.size(); if( (minSize+maxSize)%2){ // 判斷偶數奇數,注意用% // 放入最小堆 if( maxSize >0 && num<maxHeap[0]){ maxHeap.push_back(num); push_heap(maxHeap.begin(),maxHeap.end(),less<int>()); num = maxHeap[0]; pop_heap(maxHeap.begin(),maxHeap.end(),less<int>()); maxHeap.pop_back(); } minHeap.push_back(num); push_heap(minHeap.begin(),minHeap.end(),greater<int>()); }else{ // 放入最大堆 if(minSize>0 && num> minHeap[0]){ minHeap.push_back(num); push_heap(minHeap.begin(),minHeap.end(),greater<int>()); num = minHeap[0]; pop_heap(minHeap.begin(),minHeap.end(),greater<int>()); minHeap.pop_back(); } maxHeap.push_back(num); push_heap(maxHeap.begin(),maxHeap.end(), less<int>()); } } double GetMedian() { int minSize = minHeap.size(), maxSize = maxHeap.size(); if( minSize+maxSize==0) return 0.0; if( (minSize+maxSize)&1){ return maxHeap[0]; }else{ return (maxHeap[0]+minHeap[0])/2.0; } } };
使用優先佇列
class Solution { public: priority_queue<int,vector<int>, less<int> > max; priority_queue<int,vector<int>,greater<int> > min; void Insert(int num) { int maxSize = max.size(), minSize = min.size(); if((maxSize+minSize)&1){ // 放入min if(maxSize>0 && num< max.top()){ max.push(num); num = max.top(); max.pop(); } min.push(num); }else{ // 放入max if(minSize >0 && num > min.top()){ min.push(num); num = min.top(); min.pop(); } max.push(num); } } double GetMedian() { int maxSize = max.size(), minSize = min.size(); if(maxSize+minSize==0) return 0.0; if((maxSize+minSize)&1) return max.top(); else return (max.top()+min.top())/2.0; } };
P218
42. 連續子陣列的最大和
class Solution { public: int FindGreatestSumOfSubArray(vector<int> array) { int n = array.size(); if(n==0) return 0; int res = array[0]; int tmp=array[0]; for(int i=1;i<n;i++){ if( tmp + array[i] < array[i]){ // 新的序列的開始 tmp = array[i]; } else{ tmp += array[i]; // 原有序列的延續 } res = max(res,tmp); } return res; } };
P221
43. 1~n整數中1出現的次數
https://www.cnblogs.com/xuanxufeng/p/6854105.html
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{ int a, b;
int res = 0;
for(long m = 1; m<=n;m*=10){
a = n/m;
b= n%m;
res += (a+8)/10*m+((a%10==1)?b+1:0);
}
return res;
}
};
P225
44. 數字序列中某一位的數字
此題除錯了很久,最終發現問題在於 pow()函式,因此 還是自己實現吧
#include <iostream>
using namespace std;
int countOfIntegers(int digits){
if(digits==1) return 10;
else{
int tmp =1;
for(int i=0; i< digits-1;i++)
tmp *= 10;
return 9*tmp;
}
}
int findDigit(int index, int digits){
int startNum;
if(digits==1){
startNum = 0;
}
else{
startNum = 1;
for(int i=0; i< digits-1;i++)
startNum *= 10;
}
int number = startNum + index/digits;
int indexFromRight = digits - index%digits;
for(int i=0; i< indexFromRight-1;i++){
number = number/10;
}
return number%10;
}
int digitAtIndex(int index){
if(index<0)
return -1;
int digits = 1; // 位數
while(true){
int numbers = countOfIntegers(digits); // 位數確定的情況下,有多少整數
if(index < numbers*digits){ // 位數確定的情況下,容許的範圍 0 ~ numbers*digits-1
return findDigit(index, digits);
}
else {
// 在新的查詢範圍內的新的索引
index = index - numbers*digits;
digits++;
}
}
}
int main(){
cout<<digitAtIndex(0); // 0
cout<<digitAtIndex(1); // 1
cout<<digitAtIndex(9); // 9
cout<<digitAtIndex(10); // 1
cout<<digitAtIndex(189); // 9
cout<<digitAtIndex(190); // 1
cout<<digitAtIndex(1000); // 3
cout<<digitAtIndex(1001); // 7
cout<<digitAtIndex(1002); // 0
return 0;
}
P227
45. 把陣列排成最小的數
class Solution {
public:
static bool compare(int a, int b){
string strNum1 = to_string(a);
string strNum2 = to_string(b);
return (strNum1+strNum2)<(strNum2+strNum1);
}
string PrintMinNumber(vector<int> numbers) {
string res = "";
int n = numbers.size();
if(n==0) return res;
sort(numbers.begin(),numbers.end(),compare);
for(int i=0;i<n;i++){
res += to_string(numbers[i]);
}
return res;
}
};
重點在於為何這樣得到的就是最小數呢,請給出證明
P231
46. 把數字翻譯成字串
https://www.jianshu.com/p/80e1841909b7
#include <iostream>
using namespace std;
int countNum(string & number){
int len = number.length();
int counts[len];
for(int i=0;i<len;i++)
counts[i]=0;
for(int i=len-1;i>=0;i--){
if(i==len-1) counts[i]=1;
else
counts[i] += counts[i+1];
if( i< len-1){
int digit1 = number[i]-'0';
int digit2 = number[i+1]-'0';
int value = 10*digit1 + digit2;
if(value>=10 && value<=25){
if(i<len-2)
counts[i] += counts[i+2];
else
counts[i]+=1;
}
}
}
return counts[0];
}
int GetTranslationCount(int number){
if(number<0) return 0;
string str = to_string(number);
return countNum(str);
}
int main(){
cout<<GetTranslationCount(12258);
return 0;
}
P233
47. 禮物的最大價值
典型的用動態規劃解決的問題
#include <iostream>
#include <vector>
using namespace std;
int getMaxValue (vector<int> mat, int row, int col){
int n = mat.size();
if(n==0) return 0;
int res[n];
for(int i=0;i<n;i++) res[i] = mat[i];
for(int i=0;i<row;i++){
for(int j=0; j<col;j++ ){
// 對應到 i*col+j
// 左邊
int a = 0;
if(j>0) a = res[i*col+j-1];
// 右邊
if(i>0) a = max(a, res[(i-1)*col+j]);
res[i*col+j] += a;
}
}
return res[n-1];
}
int main(){
int mat[16]={1,10,3,8,12,2,9,6,5,7,4,11,3,7,16,5};
vector<int> v(mat,mat+16);
cout<<getMaxValue( v ,4,4);
return 0;
}
進一步優化,只開闢 int res[col]
P236
48.最長不含重複字元的子字串
https://leetcode.com/problems/longest-substring-without-repeating-characters/description/
下面對應leetcode, 不侷限於字母
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.empty()) return 0;
int len = s.length();
int dp[len];
int position[255]; // 用於記錄字母最新出現的位置
for(int i=0;i<255;i++)
position[i]=-1;
dp[0]=1;
position[s[0]]=0;
int maxlen = 1;
for(int i=1;i<len;i++){
if(position[s[i]]==-1){
dp[i]=dp[i-1]+1;
}else{
if( i-position[s[i]]>dp[i-1]){
dp[i] = dp[i-1]+1;
}else{
dp[i] = i-1-position[s[i]]+1;
}
}
position[s[i]]=i;
if(dp[i]>maxlen)
maxlen = dp[i];
}
return maxlen;
}
};
P240
49.醜數
每一個醜數是由其他某個醜數乘2 或3 或5得到的
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if(index==0) return 0;
int res[index];
res[0]=1;
int t2=0,t3=0,t5=0;
for(int i=1;i<index;i++){
res[i] = min(min(res[t2]*2,res[t3]*3),res[t5]*5);
if(res[i]==res[t2]*2)
t2++;
if(res[i]==res[t3]*3)
t3++;
if(res[i]==res[t5]*5)
t5++;
}
return res[index-1];
}
};
P243
50. 第一個只出現一次的字元
class Solution {
public:
int FirstNotRepeatingChar(string str) {
if(str.empty()) return -1;
int table[256];
for(int i=0;i<256;i++)
table[i]=0;
for(int i=0; i< str.length();i++)
table[str[i]]++;
for(int i=0;i<str.length();i++){
if(table[str[i]]==1)
return i;
}
return -1;
}
};
題目二:
class Solution
{
private:
int table[256];
int index=0;
public:
Solution():index(0){
for(int i=0;i<256;i++)
table[i]=-1;
}
//Insert one char from stringstream
void Insert(char ch)
{ index++;
if(table[ch]==-1)
table[ch]=index;
else
table[ch]=-2;
return ;
}
//return the first appearence once char in current stringstream
char FirstAppearingOnce()
{ int res = -1;
char ch='#';
for(int i=0;i<256;i++){
if(table[i]>=0){
if(res==-1){
ch = (char)i;
res = table[i];
}
else{
if(table[i]<res){
res = table[i];
ch = (char)i;
}
}
}
}
return ch;
}
};
P249
51.陣列中的逆序對
https://www.nowcoder.com/questionTerminal/96bd6684e04a44eb80e6a68efc0ec6c5
class Solution {
public:
int InversePairs(vector<int> data) {
// 本質上,實現歸併排序,複雜度O(nlogn),但是需要O(n)的空間
if(data.size()<=1) return 0;
vector<int> copy(data);
return InversePairsCore(data,copy,0,data.size()-1);
;
}
private:
int InversePairsCore(vector<int> & data, vector<int> & copy, int begin, int end){
if(begin==end){
copy[begin]=data[begin];
return 0;
}else{
int mid = (begin+end)/2;
int left = InversePairsCore(copy,data,begin,mid)%1000000007;
int right = InversePairsCore(copy,data,mid+1,end)%1000000007;
int cnt = 0;
int i = mid; // 前半段最後一個數字的下標
int j = end; // 後半段最後一個數字的下標
int indexCopy = end;
while(i>=begin && j>=mid+1){
if(data[i]>data[j]){
copy[indexCopy--] = data[i--];
cnt += j-(mid+1)+1;
cnt = cnt%1000000007;
}else{
copy[indexCopy--]=data[j--];
}
}
while(i>=begin){
copy[indexCopy--]=data[i--];
}
while(j>=mid+1){
copy[indexCopy--]=data[j--];
}
return (left+right+cnt)%1000000007;
}
}
};
P253
52.兩個連結串列的第一個公共節點
方法一:
開闢了空間
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
map<ListNode *, int> m;
while(pHead1){
m[pHead1]=1;
pHead1 = pHead1->next;
}
while(pHead2){
if(m.count(pHead2)==1)
break;
else
pHead2=pHead2->next;
}
return pHead2;
}
};
方法二:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
int len1=0,len2=0;
ListNode * tmp1 = pHead1,*tmp2=pHead2;
while(tmp1){
len1++;
tmp1=tmp1->next;
}
while(tmp2){
len2++;
tmp2=tmp2->next;
}
if(len1>len2){
int step=len1-len2;
while(step){
pHead1 = pHead1->next;
step--;
}
}else{
int step = len2-len1;
while(step){
pHead2 = pHead2->next;
step--;
}
}
while(pHead1){
if(pHead1==pHead2){
break;
}
else{
pHead1=pHead1->next;
pHead2=pHead2->next;
}
}
return pHead1;
}
};
P263
53.在排序陣列中查詢數字(二分查詢的加強版)
下面的方法和順序統計的複雜度一樣,是O(n), 面試官期待更高效的方法
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
if(data.empty()) return 0;
int index = binaryFind(data, k, 0,data.size()-1);
if(index==-1) return 0;
int cnt = 1;
int pre = index-1, post = index+1;
while(pre>=0){
if(data[pre]==k){
cnt++;
pre--;
}else{
break;
}
}
while(post<data.size()){
if(data[post]==k){
cnt++;
post++;
}else{
break;
}
}
return cnt;
}
private:
int binaryFind(vector<int> & data, int k, int begin, int end){
if(begin>end){
return -1;
}
int mid = (begin+end)/2;
if(k==data[mid])
return mid;
else if(k>data[mid]){
return binaryFind(data,k,mid+1,end);
}
else{
return binaryFind(data,k,begin,mid-1);
}
}
};
高效的解法:
用二分查詢定位第一次出現的位置、第二次出現的位置
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
if(data.empty()) return 0;
int firstIndex = getFirstIndex(data,k,0,data.size()-1);
if(firstIndex==-1) return 0;
int lastIndex = getLastIndex(data,k,0,data.size()-1);
return lastIndex-firstIndex+1;
}
private:
int getFirstIndex(vector<int> & data, int k, int start, int end){
if(start>end)
return -1;
int mid = (start+end)/2;
if(data[mid]==k){
if(mid>0 && data[mid-1]==k){
return getFirstIndex(data,k,start,mid-1);
}else
return mid;
}else if(data[mid]>k){
return getFirstIndex(data,k,start,mid-1);
}else{
return getFirstIndex(data,k,mid+1,end);
}
}
int getLastIndex(vector<int> & data, int k, int start, int end){
if(start>end)
return -1;
int mid = (start+end)/2;
if(data[mid]==k){
if(mid< data.size()-1 && data[mid+1]==k){
return getLastIndex(data,k,mid+1,end);
}else
return mid;
}else if(data[mid]>k){
return getLastIndex(data,k,start,mid-1);
}else{
return getLastIndex(data,k,mid+1,end);
}
}
};
擴充套件:P266
題目:0~n-1中缺失的數字
#include<iostream>
#include<vector>
using namespace std;
int findIndex(vector<int> & data, int s, int e){
if(s>e) return -1;
int mid = (s+e)/2;
if(mid==data[mid]){
return findIndex(data,mid+1,e);
}else{
if(mid>0 && data[mid-1]==mid-1 || mid==0)
return mid;
else
return findIndex(data,s,mid-1);
}
}
int main(){
vector<int> data;
data.push_back(0);
data.push_back(1);
data.push_back(2);
data.push_back(4);
data.push_back(5);
int index = findIndex(data,0,4);
if(index==-1) cout<<data.size();
else cout<<index;
return 0;
}
擴充套件:P267
陣列中數值和下標相等的元素
#include<iostream>
#include<vector>
using namespace std;
int findValue(vector<int> & data){
int left=0,right=data.size()-1,mid;
while(left<=right){
mid = (left+right)/2;
if(mid==data[mid]) return mid;
else if(data[mid]>mid){
right = mid-1;
}else{
left = mid+1;
}
}
return -1;
}
int main(){
vector<int> data;
data.push_back(-3);
data.push_back(-1);
data.push_back(1);
data.push_back(13);
data.push_back(15);
int value = findValue(data);
cout<<value;
return 0;
}
P269
54.二叉搜尋樹的第K大節點
!!!中序遍歷二叉搜尋樹,得到的結果是遞增排序的。
實現一:
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if(pRoot==NULL || k<1 ) return NULL; // 判斷k<1很重要
vector<TreeNode *> res;
inOrder(res,pRoot);
if(res.size()<k) return NULL;
else return res[k-1];
}
private:
void inOrder(vector<TreeNode *> & v, TreeNode * node){
if(node->left) inOrder(v,node->left);
v.push_back(node);
if(node->right) inOrder(v,node->right);
}
};
實現二:
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if(pRoot==NULL || k < 1) return NULL;
TreeNode * ans = NULL;
inOrder(pRoot, ans,k);
return ans;
}
private:
void inOrder(TreeNode * pRoot, TreeNode * & ans, int & k){
if(pRoot->left) inOrder(pRoot->left, ans, k);
k--;
if(k==0) {
ans = pRoot;
return ;
}
if(pRoot->right) inOrder(pRoot->right,ans,k);
}
};
P271
55.二叉樹的深度
題目一:二叉樹的深度
方法一:樹的層次遍歷
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
int TreeDepth(TreeNode* pRoot)
{ if(pRoot==NULL) return 0;
queue<TreeNode * > q;
int cnt = 0;
q.push(pRoot);
TreeNode * tmp = NULL;
while(!q.empty()){
cnt++;
for(int i=0;i<q.size();i++){
tmp = q.front();
q.pop();
if(tmp->left) q.push(tmp->left);
if(tmp->right) q.push(tmp->right);
}
}
return cnt;
}
};
方法二:遞迴
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
int TreeDepth(TreeNode* pRoot)
{
if(pRoot==NULL) return 0;
return getDepth(pRoot);
}
private:
int getDepth(TreeNode * pRoot){
int left = 0;
if(pRoot->left) left = getDepth(pRoot->left);
int right = 0;
if(pRoot->right) right = getDepth(pRoot->right);
return max(left,right)+1;
}
};
題目二:平衡二叉樹
https://leetcode.com/problems/balanced-binary-tree/submissions/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isBalanced(TreeNode* root) {
if(root==NULL) return true;
bool res = true;
getDepth(root,res);
return res;
}
private:
int getDepth(TreeNode * root, bool & res){
int left = 0;
if(root->left) left =getDepth(root->left,res);
int right = 0;
if(root->right) right = getDepth(root->right,res);
if(abs(right-left)>1) {
res = false;
}
return max(left,right)+1;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isBalanced(TreeNode* root) {
int init = 0;
return isBalancedTree(root,init);
}
private:
bool isBalancedTree(TreeNode * root, int & depth){ // depth表示當前節點的深度
if(root==NULL) {
depth=0;
return true;
}
int left =0,right=0;
if( isBalancedTree(root->left,left) && isBalancedTree(root->right,right)){
if(abs(left-right)>1) return false;
else{
depth = max(left,right)+1;
return true;
}
}
return false;
}
};
p275
56.陣列中數字出現的次數 ---- 考察二進位制與位運算
題目一:陣列中只出現一次的兩個數字
一個整型數組裡除兩個數字之外,其他數字都出現了兩次,請找出這兩個只出現一次的數字。要求時間複雜度O(n),空間複雜度O(1)
先考慮陣列中只有一個數字出現了一次,其他數字出現了兩次。
!!!任何數字異或它自己結果都等於0,從頭至尾依次異或陣列中的每個數,最後的結果是隻出現一次的那個數
class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int len = data.size();
if(len <2 ) return;
int res = 0;
for(int i=0;i<len;i++)
res ^= data[i];
int index;
int res1 = 0, res2=0;
index = findIndex(res);
for(int i=0;i<len;i++){
if( isOne(data[i],index))
res1 ^= data[i];
else
res2 ^= data[i];
}
*num1 = res1;
*num2 = res2;
}
private:
bool isOne(int value, int index){
int num=1;
num = num << (index-1);
if(value&num) return true;
else return false;
}
int findIndex(int & value){
int index = 1;
int num = 1;
while( (value&num) ==0){ // 注意加括號
index++;
num = num << 1;
}
return index;
}
};
P278
題目二:陣列中唯一隻出現一次的數字
在一個數組中除一個數字只出現一次之外,其他數字都出現了三次。
#include <iostream>
#include <vector>
using namespace std;
int FindNumberAppearingOnce(vector<int> numbers){
int len = numbers.size();
if(len <1 ) {
cout<<"invalid input";
return -1;
}
int bitSum[32]={0};
for(int i=0;i<len;i++){
int bitMask = 1;
for(int j=0;j<32;j++){
if(numbers[i]&bitMask) bitSum[j] += 1;
bitMask = bitMask << 1;
}
}
int res = 0;
for(int i=31;i>=0;i--){
res = res<<1;
res += bitSum[i]%3;
}
return res;
}
int main(){
vector<int> v;
v.push_back(2);
v.push_back(4);
v.push_back(3);
v.push_back(3);
v.push_back(3);
v.push_back(2);
v.push_back(2);
cout<<FindNumberAppearingOnce(v);
return 0;
}
P280
57.和為s的數字
題目一:和為S的兩個數字
https://www.nowcoder.com/practice/390da4f7a00f44bea7c2f3d19491311b?tpId=13&tqId=11195&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
int len = array.size();
vector<int> ans;
int a,b;
bool flag = false;
int multiply;
int left = 0, right = array.size()-1;
while(left<right){
if(array[left]+array[right]==sum){
if(flag==false){
a = array[left];
b = array[right];
multiply = a*b;
flag = true;
}else{
if(array[left]*array[right]<multiply){
a = array[left];
b = array[right];
multiply = array[left]*array[right];
}
}
left++;
right--;
}else if(array[left]+array[right]<sum){
left++;
}else{
right--;
}
}
if(flag == true) {
ans.push_back(min(a,b));
ans.push_back(max(a,b));
}
return ans;
}
};
P282
題目二:和為S的連續正數序列
https://www.nowcoder.com/practice/c451a3fd84b64cb19485dad758a55ebe?tpId=13&tqId=11194&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int>> v;
int left = 1, right = 2;
int tmp;
vector<int> res;
while(left < right && right<=(sum+1)/2){
tmp = right*(right+1)/2 - left*(left-1)/2;
if(tmp == sum){
res.clear();
for(int i=left;i<=right;i++)
res.push_back(i);
v.push_back(res);
left++;
right++;
}else if(tmp > sum){
left++;
}else{
right++;
}
}
return v;
}
};
P284
58.翻轉字串
題目一:翻轉單詞順序
class Solution {
public:
string ReverseSentence(string str) {
int start = 0, end = str.length()-1;
myReverse(str,start,end);
for(int i=0;i<str.length();i++){
if(str[i]==' '){
end = i-1;
myReverse(str,start,end);
start = i + 1;
}
}
if(str[str.length()-1]!=' ') // 翻轉最後一個單詞
myReverse(str,start,str.length()-1);
return str;
}
private:
void myReverse(string & str, int start, int end){
char tmp; // 注意用char
while(start < end){
tmp = str[end];
str[end] = str[start];
str[start] = tmp;
start++;
end--;
}
}
};
class Solution {
public:
string ReverseSentence(string str) {
int start = 0, end = str.length()-1;
myReverse(str,start,end);
start = end = 0;
while(start < str.length()){
if(str[start]==' '){
start++;
end++;
}else if(str[end]==' ' || end==str.length()){
myReverse(str,start,end-1);
start = end + 1;
end = start; // 讓兩者重逢
}else{
end++;
}
}
return str;
}
private:
void myReverse(string & str, int start, int end){
char tmp; // 注意用char
while(start < end){
tmp = str[end];
str[end] = str[start];
str[start] = tmp;
start++;
end--;
}
}
};
P287
題目二:左旋轉字串
class Solution {
public:
string LeftRotateString(string str, int n) {
int len = str.length();
if(len <= n || n<=0) return str;
myReverse(str, 0, len-1);
myReverse(str,0,len-n-1);
myReverse(str, len-n,len-1);
return str;
}
private:
void myReverse(string & str, int start, int end){
char tmp;
while(start < end){
tmp = str[end];
str[end] = str[start];
str[start]= tmp;
start++;
end--;
}
}
};
P288
59.佇列的最大值
題目一:滑動視窗的最大值
參考:https://www.jianshu.com/p/3242ddf81428
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size)
{
vector<int> res;
int n = num.size();
if(size > n || size < 1) return res;
deque<int> index;
for(int i=0;i<size;i++){ // 只考慮第一個視窗
if(index.empty()){
index.push_back(i);
}else{
while(!index.empty() && num[index.back()]< num[i]){
index.pop_back();
}
index.push_back(i);
}
}
res.push_back(num[index.front()]);
for(int i = size; i < n; i++){ // 開始滑動
while(!index.empty() && num[index.back()] < num[i]){
index.pop_back();
}
index.push_back(i);
if(i-index.front()==size){ // 要滑出首端數字
index.pop_front();
}
res.push_back(num[index.front()]);
}
return res;
}
};
題目二:佇列的最大值
P294
60. n個骰子的點數
方法一:遞迴
其實就是深度優先,把每條路徑的和都求出來
#include <iostream>
using namespace std;
void gopath(int * record, int number,int sum,int n){
if(number==0) {
record[sum-n]++;
return ;
}
for(int i=1;i<=6;i++){
gopath(record, number-1,sum+i,n);
}
}
void printprob (int n){
if(n<1) return ;
int maxsum = 6*n;
int record[maxsum-n+1]={0};
gopath(record,n,0,n);
for(int i=0; i< maxsum-n+1;i++)
cout<<record[i]<<endl;
}
int main(){
printprob(2);
return 0;
}
方法二:基於迴圈,時間效能更好
P298
61. 撲克牌中的順子
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
int n = numbers.size();
if(n == 0) return false;
sort(numbers.begin(),numbers.end());
int zero_cnt = 0;
for(int i=0;i<n;i++){
if(numbers[i]==0) zero_cnt++;
else{
if(i<n-1){
if(numbers[i+1]==numbers[i]) return false;
else{
zero_cnt = zero_cnt - (numbers[i+1]-numbers[i]-1);
if(zero_cnt<0) return false;
}
}
}
}
return true;
}
};
P300
62.圓圈中最後剩下的數字
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<=0 || m<=0) return -1;
int number[n];
for(int i=0;i<n;i++)
number[i]=0;
int cnt = n;
int index=0;
while(cnt>1){
for(int i=1;i<=m;i++){
while(number[index%n]==1){
index++;
}
if(i==m){
number[index%n]=1;
cnt--;
}
index++;
}
}
while(number[index%n]==1)
index++;
return index%n;
}
};
用vector
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<=0 || m<=0) return -1;
vector<int> v;
for(int i=0;i<n;i++)
v.push_back(i);
vector<int>::iterator it = v.begin(); // 注意先後順序
while(v.size()>1){
for(int i=1;i<=m;i++){
if(it == v.end()){
it = v.begin();
}
if(i==m){
it = v.erase(it);
}else{
it++;
}
}
}
if(it == v.end()) it = v.begin(); // 這一行十分關鍵
return *it;
}
};
簡單的方法,但是數學推導分析
https://blog.csdn.net/u010429424/article/details/73695062
f(n,m)表示最後剩下的數字
f(n,m) =( f(n-1,m)+m)%n
class Solution {
public:
int LastRemaining_Solution(int n, int m)
{
if(n<=0 || m<=0) return -1;
int before=0;
for(int i=2;i<=n;i++){
before = (before+m)%i;
}
return before;
}
};
P304
63.股票的最大利潤
https://leetcode.com/problems/best-time-to-buy-and-sell-stock/submissions/
- Best Time to Buy and Sell Stock
只有一次交易,遍歷陣列,每遍歷一個數表示當前被賣,那麼只需記錄當前之前的最小值(買入),兩者做差看利益是否是最大。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int maxProfit = 0;
int n = prices.size();
if(n<=1) return 0;
int minbefore = prices[0];
for(int i=1;i<n;i++){
if(prices[i]-minbefore > maxProfit){
maxProfit = prices[i]-minbefore;
}
if(minbefore > prices[i])
minbefore = prices[i];
}
return maxProfit;
}
};
擴充套件:
- Best Time to Buy and Sell Stock II
支援多次交易,如果後一天的數值大於當天的數值,就把差值加入到最大收益中。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
int maxProfit = 0;
if(n<=1) return 0;
for(int i=0;i<n-1;i++){
if(prices[i+1]-prices[i]>0)
maxProfit += prices[i+1]-prices[i];
}
return maxProfit;
}
};
-
Best Time to Buy and Sell Stock III
最多進行2次交易, -
Best Time to Buy and Sell Stock IV
-
Best Time to Buy and Sell Stock with Transaction Fee
-
Best Time to Buy and Sell Stock with Cool down
P307
64. 求1+2+…+n
略,看pdf
P310
65.不用加減乘除做加法
class Solution {
public:
int Add(int num1, int num2)
{ int tmp1,tmp2;
while(num2!=0){
tmp1 = num1^num2;
tmp2 = num1&num2;
tmp2 = tmp2<<1;
num1=tmp1;
num2=tmp2;
}
return num1;
}
};
P313
66.構建乘積陣列
class Solution {
public:
vector<int> multiply(const vector<int>& A) {
int n = A.size();
vector<int> res;
if(n==0) return res;
int tmp = 1;
for(int i=0;i<n;i++){
res.push_back(tmp);
tmp = tmp * A[i];
}
tmp = 1;
for(int i=n-1;i>=0;i--){
res[i] = res[i]*tmp;
tmp = tmp * A[i];
}
return res;
}
};
P318
67. 把字串轉換成整數
class Solution {
public:
int state = 1; // 1代表不合法,0代表合法
int StrToInt(string str) {
long long number=0;
if(str=="") {
return 0;
}else{
int minus = 1;
int start = 0;
if(str[0]=='+'){
start++;
}else if(str[0]=='-'){
minus = -1;
start++;
}
if(start < str.length()){
for(int i=start;i<str.length();i++){
if(str[i]>='0' && str[i]<='9'){
number = number*10+(str[i]-'0')*minus;
if( (minus==1 && number > 0x7FFFFFFF) || (minus==-1 && number < (signed int)0x80000000))
return 0;
}else{
return 0;
}
}
state = 0;
return (int)number;
}else{
return 0;
}
}
}
};
P326
68.樹中兩個節點的最低公共祖先