牛客劍指offer刷題記錄(一)
1.二維陣列查詢
本題的關鍵就在於二維陣列具有一定的特性:
從左往右,從上往下呈遞增序列。
如果二次遍歷,就失去了這個題目的意義因為複雜度是
對於這個矩陣來說,左上角的值
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
int m = array.size();
int n = array[0].size();
if (m == 0 || n == 0)
return false;
int i = 0;
int j = n - 1;
while ((i < m)&&(j >= 0))
{
if (array[i][j] < target)
++i;
else if (array[i][j] > target)
--j;
else
return true;
}
return false;
}
};
2.替換空格
這題主要是考察,對陣列擴容的時候可以先計算擴容後的大小,比如這題,先計算空格有多少個,然後加上原有字元的個數,就是擴容後的大小。最後插入的時候從後往前操作,可以保證演算法的原地的執行(in place)
此題的擴充套件就是,兩個排好序的數組合併成一個有序陣列,可以考慮先對其中一個數組進行擴容,之後再把另一個數組的值從後往前插入。
class Solution {
public:
void replaceSpace(char *&str,int length) {
if(NULL==str)
return;
char *p=str;
int space=0;
while(*p!='\0')
{
if(*p==' ')
++space;
++p;
}
char *copy= (char *)malloc((2*space+length+1)*sizeof(char));
*(copy+2*space+length)='\0';
int j=2*space+length-1;
int i=length-1;
while(i>=0)
{
if(*(str+i)==' ')
{
*(copy+j)='0';
*(copy+j-1)='2';
*(copy+j-2)='%';
j-=3;
--i;
}
else
{
*(copy+j)=*(str+i);
--j;
--i;
}
}
char *tmp=copy;
copy=str;
str=tmp;
cout<<str<<endl;
}
};
3.從尾到頭列印連結串列
連結串列這個資料結構,如果指標域是單向的,那麼它的迭代也是單向的,也即不能向陣列那樣,隨機的訪問最後一個元素,再往前列印。
解決的方案有很多。最直觀的方法是,從前往後遍歷,然後將遍歷的value壓棧,這樣彈棧的時候就是原連結串列相反的順序。
遞迴是另一種形式,遞迴的呼叫函式使其以連結串列的下一個節點做當前節點,就達到了遍歷的效果,然後在遞迴返回之際列印相應值,就反序了。因為遞迴其實就是函式棧,所以思想跟上一個差不多
class Solution {
private:
void help(ListNode * head,vector<int>&v)
{
if(head!=NULL)
{
if(head->next!=NULL)
{
help(head->next,v);
}
v.push_back(head->val);
}
}
public:
vector<int> printListFromTailToHead(ListNode* head) {
if(NULL==head)
return vector<int>();
vector<int>tmp;
help(head,tmp);
return tmp;
}
};
4.重建二叉樹
此題的擴充套件就是,假設我們現在要序列化一個二叉樹,那麼我們可以儲存其先序和中序的序列,資料到remote端以後,然後再rebuild一下。
先序遍歷序列找到根節點,中序遍歷序列將又通過根節點劃分兩個左右子樹。為了方便快捷的在中序遍歷的序列中找到根節點所在位置,可以用一個map記錄根節點值和索引的key-value對。
此外,在先序遍歷中,要找到子樹根的位置,還必須通過中序遍歷計算劃分之後,左子樹和右子樹的節點個數。因此,我用了4個引數來記錄:
preStart//子樹先序開始
preEnd//子樹先序結束
inStart//子樹中序開始
inEnd//子樹中序結束
遞迴的方式去構建二叉樹,每次都去更新這些數的值
class Solution {
private:
TreeNode * help(vector<int>&pre,//pre seq
vector<int>&vin,//in seq
int preStart, //pre start idx
int preEnd, //pre end idx
int inStart, //in start idx
int inEnd, //in end idx
unordered_map<int, int>&index)// map find idx in vin
{
if (inStart > inEnd)//
{
return NULL;
}
//先拿到根節點的值
int rootval = pre[preStart];//root val
//建立根節點
TreeNode * root = new TreeNode(rootval); //root node
//找到中序遍歷中根節點的索引
int idx = index[rootval];//root index in vin
//split vin with idx
//通過索引計算中序中對左右子數的劃分(計算節點的個數),以便在先序中找到子樹的根
//遞迴左子樹
root->left = help(pre, vin, preStart + 1, preStart + idx - inStart, inStart, idx - 1, index);
//遞迴右子樹
root->right = help(pre, vin, preStart + idx - inStart + 1, preEnd, idx + 1, inEnd, index);
return root;
}
public:
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin)
{
unordered_map<int, int>index;
//計算中序遍歷序列中 值和索引的Key-value對
for (int i = 0; i < vin.size(); ++i)
{
index[vin[i]] = i;
}
return help(pre, vin, 0, pre.size() - 1, 0, vin.size() - 1, index);
}
};
5.兩個棧實現佇列
棧是後進先出,first-in-last-out
佇列是先進先出,first-in-first-out
現在由兩個棧,將元素插入到第一個棧中,再逐個彈出壓入第二個棧中,這樣在棧1中先入棧的元素,到了棧2中就越靠近棧頂,然後從棧2中彈棧,就達到了FIFO的效果。
這裡,不是每次彈棧都要講棧1的序列全部壓入棧2,只有當棧2為空的時候才這樣做。
class Solution
{
public:
void push(int node)
{
stack1.push(node);
}
int pop()
{
if(!stack1.empty()||!stack2.empty())
{
if(stack2.empty())
{
while(!stack1.empty())
{
stack2.push(stack1.top());
stack1.pop();
}
}
int t=stack2.top();
stack2.pop();
return t;
}
return -1;
}
private:
stack<int> stack1;
stack<int> stack2;
};
相關推薦
牛客劍指offer刷題記錄(一)
1.二維陣列查詢 本題的關鍵就在於二維陣列具有一定的特性: 從左往右,從上往下呈遞增序列。 如果二次遍歷,就失去了這個題目的意義因為複雜度是O(n2) 對於這個矩陣來說,左上角的值a(0,0)一定為最小值,右下角的值a(m,n)一定是最大值,當與ta
劍指offer刷題記錄11——二進位制中1的個數
題目描述 輸入一個整數,輸出該數二進位制表示中1的個數。其中負數用補碼錶示。 將輸入的整數分成0,正,負三種情況分別討論。正數和0不必多說,當負數時,要將反碼的32位用0補全,補碼是取反加一,再求1的個數,所以可以不必求補碼,直接轉化成反碼加0,1和0的代數關係進行調
劍指offer刷題記錄14——連結串列中倒數第k個結點
題目描述 輸入一個連結串列,輸出該連結串列中倒數第k個結點。 想到利用雙指標標記頭部,移動第二個指標直到距離為k - 1,再同時移動兩個指標,當第二個指標指向尾部,第一個指標則指向倒數第k個結點。 解法一: public class Solution {
劍指offer刷題記錄17——樹的子結構
題目描述 輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構) 解法一:遞迴 public class Solution { public boolean HasSubtree(TreeNode root1, TreeN
劍指offer刷題記錄20——包含min函式的棧
題目描述 定義棧的資料結構,請在該型別中實現一個能夠得到棧中所含最小元素的min函式(時間複雜度應為O(1))。 解法: import java.util.Stack; import java.util.Iterator; public class Solutio
劍指offer刷題記錄26——二叉搜尋樹與雙向連結串列
題目描述 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。 public class Solution { public TreeNode Convert(TreeNode root) {
劍指offer刷題記錄25——複雜連結串列的複製
題目描述: 輸入一個複雜連結串列(每個節點中有節點值,以及兩個指標,一個指向下一個節點,另一個特殊指標指向任意一個節點),返回結果為複製後複雜連結串列的head 因為是一個複雜連結串列,每個節點有一個random屬性,導致無法採用簡單的一個一個節點進行復制的方法。 故而
劍指offer刷題記錄
連續子陣列的最大值 要求:例如:{6,-3,-2,7,-15,1,2,2},連續子向量的最大和為8(從第0個開始,到第3個為止)。給一個數組,返回它的最大連續子序列的和 class Solution { public: int FindGre
劍指Offer 刷題筆記(20/66)——JAVA
文章目錄 11.二進位制中1的個數 12.數值的整數次方 13.調整陣列順序使奇數位於偶數前面 14.連結串列中倒數第k個節點 15.反轉連結串列 16.合併兩個排序的連結串列 17.樹的
劍指Offer刷題筆記(java實現)_26.樹的子結構
題目描述: 輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)。 其實思路很簡單:我們的演算法就通過比較即可,因為是樹的遍歷比較所以第一時間想到了遞迴 先假設母樹為A,子樹為B (1)我們先去判斷節點的第一個點的值是
劍指Offer刷題筆記(java實現)_39.陣列中次數超過一半的數字
陣列中有一個數字出現的次數超過陣列長度的一半,請找出這個數字。 例如輸入陣列:{1,3,3,2,3,2,3,3,2}。由於2在陣列中出現了5次,超過陣列長度的一半,因此要輸出2。 三種解法: 第一種遍歷陣列,利用hashMap儲存每個數字出現的次數,時間複雜度O(n)
劍指Offer 刷題筆記(30/66)——JAVA
文章目錄 21.棧的壓入、彈出序列 22.從上往下列印二叉樹 23.二叉搜尋樹的後序遍歷序列 24.二叉樹中和為某一值的路徑 25.複雜連結串列的複製 26.二叉搜尋樹與雙向連結串列 27
劍指Offer 刷題筆記(10/66)——JAVA
如果你碰巧點進來想看解題思路的話,可以看下這位dalao寫的.挺詳細的~ https://blog.csdn.net/flushhip/article/details/79392028#commentBox 文章目錄 1.二維陣列中的查詢
劍指offer刷題心得(面試篇)
行為面試=》技術面試=》應聘者提問 1. 行為面試環節 專案經驗是重中之重,簡歷撰寫參考STAR模型:即Situation(簡短的專案背景),Task(完成的任務),Action(為完成任務做了哪些工作,怎麼做的),Result(自己的貢獻)
LeetCode刷題記錄(一)
LeetCode刷題記錄(一) 最近開始在LeetCode上面做題,想想應該做一個記錄,以便以後看到類似的問題及時查閱,同時也能夠將做題時的思路記錄下來,將這些思路整理歸納,形成一套我自己的解題思路。當然,演算法題只做一次是不夠的,需要多次的練習,可能每次的想法都不太一樣,在這裡我只
關於牛客網劍指offer程式設計題思路(棧和佇列篇)
相關題目來源 解題思路 1. 用兩個棧實現佇列 這道題阿里電話面試的時候問過,本來很簡單的,當時太不自信了qaq 首先一個stack是作為接受佇列的push輸入,另一個stack作為輸出pop,用效率比較高的方法是要pop的時候檢查一下stac
二維數組中的查找——牛客劍指offer
劍指offer 比較 direct [] data- ring 要求 als 步驟 題目描述: 在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是
鏈表分割——牛客劍指offer
之前 排列 頭指針 print lse 遍歷 lis 例如 自建 題目描述: 編寫代碼,以給定值x為基準將鏈表分割成兩部分,所有小於x的結點排在大於或等於x的結點之前 給定一個鏈表的頭指針 ListNode pHead,請返回重新排列後的鏈表的頭指針。註意:分割以後保持原來
劍指offer刷題之反轉連結串列
題目描述 輸入一個連結串列,反轉連結串列後,輸出新連結串列的表頭。 # -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): #  
劍指offer刷題之連結串列中倒數第k個結點
題目描述 輸入一個連結串列,輸出該連結串列中倒數第k個結點。 # -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # s