題目描述
輸入一個矩陣,按照從外向裏以順時針的順序依次打印出每一個數字,例如,如果輸入如下矩陣: 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.
見:劍指offer第128頁
class Solution {
public:
vector<int> printMatrix(vector<vector<int> > matrix) {
int row=matrix.size();
int col=matrix[0].size();
vector<int> result;
if(row==0||col==0) return result;
int start=0;//每一圈左上角的數的橫縱座標相等,均爲start
while(col>start*2&&row>start*2){
int endX=col-1-start; //第start圈的最後一列的座標 終止列號
int endY=row-1-start; //第start圈的最後一行的座標 終止行號
for(int i=start;i<=endX;i++) result.push_back(matrix[start][i]); //第一行總是存在的
if(start<endY){//只有當至少還有兩行時,才需要執行從上到下的遍歷 起始行號小於終止行號
for(int i=start+1;i<=endY;i++) result.push_back(matrix[i][endX]);
}
if(start<endX&&start<endY){ //只有當至少還有兩行兩列時,才需要執行從右到左的遍歷 起始行號小於終止行號且起始列號小於終止列號
for(int i=endX-1;i>=start;i--) result.push_back(matrix[endY][i]);
}
if(start<endX&&start<endY-1){ //只有當至少有三行兩列時,才需要執行從下到上的遍歷 起始行號比終止行號小2且起始列號小於終止列號
for(int i=endY-1;i>=start+1;i--) result.push_back(matrix[i][start]);
}
start++;//圈數+1
}
return result;
}
};
題目描述
輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否爲該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對應的一個彈出序列,但4,3,5,1,2就不可能是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
if(pushV.size()!=popV.size()) return false;
if(pushV.size()==0) return true;
stack<int> s;
int index=0; //popV的索引
int index2=0; //pushV的索引
while(index<popV.size()&&index2<pushV.size()){
while(index2<pushV.size()&&(s.empty()||s.top()!=popV.at(index))){//當棧爲空或者棧頂元素不是下一個待彈出的元素,就將下一個元素入棧
s.push(pushV.at(index2));
index2++;
}
while(index<popV.size()&&s.top()==popV.at(index)){//當棧頂元素是待彈出元素,就將其彈出
s.pop();
index++;
}
}
if(s.empty()) return true;//若待壓入序列已經全部壓入,但是並沒有被全部彈出,此時棧非空
return false;
}
};
題目描述
從上往下打印出二叉樹的每個節點,同層節點從左至右打印。
//思路1:使用兩個vector,每一層佔用一個,輪流使用
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int> result;
if(root==NULL) return result;
vector<TreeNode*> v1;
vector<TreeNode*> v2;
v1.push_back(root);//先將根節點加入v1
while(v1.size()!=0||v2.size()!=0){
if(v1.size()!=0){//遍歷v1中的節點,打印其值,並將各自的左右子節點加入v2
for(int i=0;i<v1.size();i++){
result.push_back(v1[i]->val);
if(v1[i]->left!=NULL) v2.push_back(v1[i]->left);
if(v1[i]->right!=NULL) v2.push_back(v1[i]->right);
}
v1.clear();//遍歷完之後清除v1
}
if(v2.size()!=0){//遍歷v2中的節點,打印其值,並將各自的左右子節點加入v1
for(int i=0;i<v2.size();i++){
result.push_back(v2[i]->val);
if(v2[i]->left!=NULL) v1.push_back(v2[i]->left);
if(v2[i]->right!=NULL) v1.push_back(v2[i]->right);
}
v2.clear();//遍歷完之後清除v2
}
}
return result;
}
};
//思路2:使用隊列,每次從隊列中取出一個節點,然後將其左右節點入隊
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int> result;
if(root==NULL) return result;
queue<TreeNode* > q;
q.push(root);
while(!q.empty()){
TreeNode* node=q.front();
q.pop();
result.push_back(node->val);
if(node->left!=NULL) q.push(node->left);
if(node->right!=NULL) q.push(node->right);
}
return result;
}
};
題目描述
輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的所有路徑。路徑定義爲從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。
思路:遞歸,使用vector記錄路徑,使用先序遍歷的方式訪問節點,將節點添加到路徑上,並累加該節點的值,如果該節點爲葉子節點且路徑中節點值之和等於給定值,則該路徑符合要求,存儲路徑,然後遞歸回到其父節點。注意在退出之前要在路徑上刪除當前節點並減去當前節點的值。
class Solution {
public:
vector<vector<int>> result;
void find(TreeNode* root,int expectNumber,vector<int> path,int currentNumber){
currentNumber+=root->val; //當前的和
path.push_back(root->val); //把當前節點加入路徑中
bool isleaf=(root->left==NULL&&root->right==NULL); //判斷是不是葉子節點
if(currentNumber==expectNumber&&isleaf){ //如果是葉子節點且當前和等於給定的數
result.push_back(path);
}
if(root->left!=NULL) find(root->left,expectNumber,path,currentNumber); //如果不是葉子節點,則遞歸遍歷子樹
if(root->right!=NULL) find(root->right,expectNumber,path,currentNumber);
path.pop_back(); //先序遍歷,回到父節點之前將當前節點從路徑中刪除
}
vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
if(root==NULL) return result;
vector<int> path;
find(root,expectNumber,path,0);
return result;
}
};
題目描述
一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。
思路:兩個相同的數字的異或爲0,先將所有數字進行異或,結果其實是兩個不同的數字異或的結果,然後找到這兩個數字異或後爲1的數位,以此位將所有數字分爲兩組,則這兩個數字必定出現在不同的組內,問題就轉化成了找一組數據中只出現一次的一個數字的問題,只需要將兩組數字分別進行異或,結果就是這兩個數字。
class Solution {
public:
int find(vector<int> v){
int res=0;
for(int i=0;i<v.size();i++){
res=res^v[i];
}
return res;
}
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
if(data.size()<2) return ;
int r=0; //注意,異或前初始化爲0,0和任意數的異或結果爲該數本身
for(int i=0;i<data.size();i++){
r=r^data[i];//所有數字進行異或
}
int index=0;
while(r){
if(r&1) break;//找到異或後爲1的數位
else{
index++;
r=r>>1;
}
}
int temp=1<<index;
vector<int> v1;
vector<int> v2;
for(int i=0;i<data.size();i++){//以爲1 的位維基準,將所有數據劃分爲兩組
if(data[i]&temp) v1.push_back(data[i]);
else v2.push_back(data[i]);
}
*num1=find(v1);//轉化成在一組數據中找只出現一次的數
*num2=find(v2);
}
};