为什么下面的代码会同时输出78而不是鞍点呢
#include <stdio.h>
int main()
{
int a[][2]={1,3,7,8};
int i,k,max[2],min[2],t;
for(k=0;k<2;k++)
{
for(max[k]=a[0][k],i=0;i<2;i++)
{
if(max[k]<a[i][k])
{
max[k]=a[i][k];
}
}
}
for(t=0;t<2;t++)
{
for(min[t]=a[t][0],i=0;i<2;i++)
{
if(min[t]>a[t][i])
{
min[t]=a[t][i];
}
}
}
for(k=0;k<2;k++)
{
if(min[k]==max[k])
printf("%d",min[k]);
}
return 0;
}
你的程序应该根本没有输出
leetcode. 二叉树的前序遍历
前提提示:
一.这里的NULL我们不用访问,访问在这里相当于入一个数组(vector),不懂的同学先把他当成数组!
二. 以及这里所说的最左列为当前节点一直递归它的左子树,即上图的1 , 2,4
分析:我们想要利用栈对我们的二叉树进行前序遍历,我们可以观察前序遍历的时候会先遍历
1–>2–>4,我们一边遍历一边将遍历的值放入栈中看看。发现这棵树的话只剩下4,2,1的右子树就可以走完了!!!!
如何遍历右子树呢? 实际上我们观察**(3)这颗子树我们可以发现什么,我们没有办法通过一次操作遍历完右子树,但是我们可以把3这颗子树进行拆分,我们入它的最左列节点访问再进行入栈**,就相当于遍历了(3)的左子树与每个节点的根(细品),这个时候我们遍历(7)是不是就是一次操作就能解决了?其实还可以再分一次,分到像(5)的时候,当节点的右子树为空树的时候,我们就访问他!!!
重要:
一棵树一定能分到没有右子树的时候,这时访问当前节点相当于访问上一个根节点的右子树
一棵树一定能分到没有右子树的时候,这时访问当前节点相当于访问上一个根节点的右子树
一棵树一定能分到没有右子树的时候,这时访问当前节点相当于访问上一个根节点的右子树
就像访问5的时候是不是相当于访问了2的右子树?是的!
💖💖💖💖💖💖
上面没看懂,没关系,带大家再走一下每一个步骤
💖💖💖💖💖💖
这里再拆分一下每一个步骤
刚开始
第一步:我们就访问每一个节点并且入栈(将1,2,4入栈并且放入数组),这时候我们要拿出栈顶的4,将它的右子树的最左列入栈(NULL不入栈),我们重复此操作,到2的时候,我们将它的右子树(5)及其最左列入栈并且访问,并且把2出栈,这时候的栈只有(5,1)
重复上述操作,取栈顶数据,将栈顶数据的右子树的最左列入栈之后将原栈顶数据出栈,这里5右子树为NULL不用入栈,我们栈里就只剩下1,接着入1的右子树的最左列,即3,6入栈
重复上述操作,取栈顶数据,将栈顶数据的右子树的最左列入栈之后将原栈顶数据出栈,6无右子树,就弹出了,到3的时候把3的右子树最左列带入(7),最后栈里面还有一个7
重复上述操作,取栈顶数据,将栈顶数据的右子树的最左列入栈之后将原栈顶数据出栈,把7出掉,结束!!!!
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
//利用栈进行迭代遍历
//思路:每次遍历当前节点(cur)的左子树,再进行入栈,最后从栈中依次取出以相同的方式遍历右子树
//可以先入最左的树
TreeNode* cur =root;
vector<int> retArr;//用来返回的答案
stack<TreeNode*> s;//利用栈进行迭代遍历
while(cur)
{
retArr.push_back(cur->val);
s.push(cur);
cur = cur->left;
}
//现在只要遍历栈当中的所有的右子树就遍历完所有树
//当然遍历每个右子树也不是一次就能搞定的,我们分解成遍历每个右子树和他的左子树,...在遍历他的右子树,就类似我们的递归遍历
while(!s.empty())
{
//我们可以对于栈当中的右子树一个一个处理
cur = s.top();
s.pop();
cur = cur->right;
//将右子树的最左列也都入栈
while(cur)
{
//每个右子树又会带出更多的右子树....
retArr.push_back(cur->val);
s.push(cur);
cur =cur->left;
}
}
return retArr;
}
};
//分析子过程,这里是第一步,将root即右子树的最左列入栈
while(cur)
{
//每个右子树又会带出更多的右子树....
retArr.push_back(cur->val);
s.push(cur);
cur =cur->left;
}
总结,我们面对这种题都可以先入该节点及它的最左列节点,然后我们上面这一段代码再去带出右子树当中的最左列,当我们带出来的时候相当于所有的根与左子树已经遍历完了,我们只用对右子树处理。右子树又可以被继续拆分!!!
while(!s.empty())
{
//我们可以对于栈当中的右子树一个一个处理
cur = s.top();
s.pop();
//取出当前节点所有的右子树,没有就在后面的循环中拿出这个值(相当于访问上一个根的右子树)
cur = cur->right;
//将右子树的最左列也都入栈
while(cur)
{
//每个右子树又会带出更多的右子树....
retArr.push_back(cur->val);
s.push(cur);
cur =cur->left;
}
}
问题回答: 要找出一个二维数组的鞍点,需要满足在该行上最大,在该列上最小,可以通过双重循环比对每一个元素,找到符合条件的元素即为鞍点。
下面的代码输出78而不是鞍点,是因为只是打印了第三行,没有比对每一个元素找到符合条件的鞍点。需要在函数内部增加比对每一个元素的代码,以下是修改后的代码:
int findSaddlePoint(int arr[][5], int rowSize, int colSize){
int saddle = -1; // 记住鞍点
for(int i = 0; i < rowSize; ++i){
int minInRow = arr[i][0]; // 找到一行中的最小值
int pos = 0; // 最小值在该行的列
for(int col = 1; col < colSize; ++col){ // 找到该行中的最小数和列位置
if(arr[i][col] < minInRow){
minInRow = arr[i][col];
pos = col;
}
}
bool found = true; // 判断是否为鞍点
for(int j = 0; j < rowSize; ++j){
if(arr[j][pos] > minInRow){ // 不满足最小条件为非鞍点
found = false;
break;
}
}
if(found){ // 如果是鞍点则返回
saddle = minInRow;
break;
}
}
return saddle;
}
int main(){
int arr[3][5] = { {1,2,3,4,5} ,{2,3,4,5,6}, {3,4,5,6,7} };
int saddle = findSaddlePoint(arr, 3, 5);
if(saddle == -1){
cout << "该二维数组不存在鞍点" << endl;
}else{
cout << "该二维数组的鞍点为: " << saddle << endl;
}
return 0;
}
输出结果将会是 "该二维数组不存在鞍点",因为该数组不存在鞍点。
解释:
先在每行中找到最小值和其位置,如果存在某一行的最小值不是该列上的最大值,则不是鞍点。所有行都找完则没有鞍点。同时增加了找到鞍点后返回的代码,将鞍点值直接返回。