剑指offer 刷题记录

No1 二维数组中的查找

牛客网原题链接

题目描述

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

[
 [1,2, 8, 9],
 [2,4, 9,12],
 [4,7,10,13],
 [6,8,11,15]
]

给定 target = 7,返回 true。

给定 target = 3,返回 false。

解题思路

二维数组左上角元素是最小的,右下角元素是最大的,从左下角向上逐渐减小,向右逐渐增大,可以采用二分法,从左下角开始比较。

  • 如果当前元素比target小,则row--;
  • 如果当前元素比target大,则额col++;
  • 如果相等,返回true;
  • 如果越界还没找到没,说明不存在,返回false。
class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        if(array.size() == 0)
            // 如果行数为0
            return false;
        if(array[0].size() == 0)
            // 如果列数为0
            return false;
        int row = array.size();
        int col = array[0].size();
        int i = row-1;
        int j = 0;
        while(i >= 0 && j < col){
            if(array[i][j] > target)
                i--;
            else if(array[i][j] < target)
                j++;
            else
                return true;
        }
        return false;
    }
};

No2 替换空格

牛客网原题链接

题目描述

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

解题思路

int length; length指的是字符串实际长度(不包含'\0')

题目有歧义,无法判断内存空间是否足够存放替换后的字符串,若不能存放,需要另开辟空间。

答案假设可以存放。

/*
问题1:替换字符串,是在原来的字符串上做替换,还是新开辟一个字符串做替换!
问题2:在当前字符串替换,怎么替换才更有效率。
      从前往后替换,后面的字符要不断往后移动,要多次移动,所以效率低下
      从后往前,先计算需要多少空间,然后从后往前移动,则每个字符只移动一次,这样效率更高一点。
*/
class Solution {
public:
	void replaceSpace(char *str,int length) {
        int spaceConut = 0;
        for(int i = 0; i < length; i++){
            if(str[i] == ' '){
                spaceConut++;
            }
        }
        // totalLen需要的总长度
        int totalLen = length + spaceConut * 2;
        str[totalLen] = '\0';
        for(int i = length - 1; i >=0; i--){
            if(str[i] == ' '){
                str[--totalLen] = '0';
                str[--totalLen] = '2';
                str[--totalLen] = '%';
            }
            else
                str[--totalLen] = str[i];
        }
	}
};

N0.3 从尾到头打印链表

牛客网原题链接

题目描述

输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)。

image-20220804125429753

解题思路

这题很简单。。从前向后保存,然后reverse就可以了

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        if(head == nullptr)
            return vector<int>();
        vector<int> ret;
        while(head != nullptr){
            ret.emplace_back( head->val);
            head = head->next;
        }
        
        reverse(ret.begin(), ret.end());
        return ret;
        // return vector<int>(ret.rbegin(), ret.rend());  // 或者直接返回反转容器
    }
};

No4 重建二叉树

重建二叉树_牛客网

题目描述

给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。

例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。

image-20220804163407216

解题思路

  • step 1:先根据前序遍历第一个点就是根节点,建立根节点。
  • step 2:然后遍历中序遍历找到根节点所在位置。
  • step 3:再按照子树的节点数将两个遍历的序列分割成子数组,将子数组送入函数建立子树。
  • step 4:直到子树的序列长度为0,结束递归。
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        // 若先序遍历、中序遍历都为0(或者有一个为0),即空二叉树
        int n = pre.size();
        int m = vin.size();
        if(n == 0 && m ==0){
            return nullptr;
        }
        
        TreeNode *root = new TreeNode(pre[0]);
        for(int i = 0; i < m; i++){
            // 在中序遍历中找到先序遍历的第一个元素
            if(pre[0] == vin[i]){
                // 左子树的先序遍历
                vector<int> leftpre(pre.begin() + 1, pre.begin() + i + 1);
                // 左子树的中序遍历
                vector<int> leftvin(vin.begin(), vin.begin() + i);
                // 构建左子树
                root->left = reConstructBinaryTree(leftpre, leftvin);
                
                // 右子树的先序遍历
                vector<int> rightpre(pre.begin()+ i + 1, pre.end());
                // 右子树的中序遍历
                vector<int> rightvin(vin.begin()+ i + 1, vin.end());
                // 构建右子树
                root->right = reConstructBinaryTree(rightpre, rightvin);
                
                break;
            }           
        }
        return root;
    }
};

No5 用两个栈来实现一个队列

用两个栈实现队列 牛客网

题目描述

用两个栈来实现一个队列,使用n个元素来完成 n 次在队列尾部插入整数(push)和n次在队列头部删除整数(pop)的功能。 队列中的元素为int类型。保证操作合法,即保证pop操作时队列内已有元素。

解题思路

class Solution
{
public:
    // 入队列正常入栈
    void push(int node) {
        stack1.push(node);
    }

    int pop() {
        // 将所有栈1 元素 反向放入 栈2
        // 将栈1的最上方元素放入栈2 栈1出栈
        while(!stack1.empty()){
            stack2.push(stack1.top());
            stack1.pop();
        }
        
        // pop指令 弹出top元素
        int res = stack2.top();
        stack2.pop();
        
        // 再将栈2元素 反向放回 栈1
        while(!stack2.empty()){
            stack1.push(stack2.top());
            stack2.pop();
        }
        return res;
    }

private:
    stack<int> stack1;
    stack<int> stack2;
};

No6 旋转数组

题目描述

有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。

数据范围:1 ≤ n ≤ 10000 1 ≤ n ≤10000,数组中任意元素的值: 0 ≤ val ≤ 10000 0 ≤ val ≤ 10000

要求:空间复杂度:O(1),时间复杂度:O(logn)

解题思路

解法1:这不就是找最小值么,常规解法,但是时间复杂度为O(n);或者使用sort排序容器

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size() == 0)
            return 0;
        int res = rotateArray[0];
        for(int i = 1; i < rotateArray.size(); i++){
            if(res > rotateArray[i]){
                res = rotateArray[i];
            }
        }
        return res;
    }
};

解法2:二分法

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        int left = 0;
        int right = rotateArray.size() - 1;
        while(left < right){
            int mid = (left + right) / 2;
            //最小的数字在mid右边
            if(rotateArray[mid] > rotateArray[right]) 
                left = mid + 1;
            //无法判断,一个一个试
            else if(rotateArray[mid] == rotateArray[right]) 
                right--;
            //最小数字要么是mid要么在mid左边
            else 
                right = mid;
        }
        return rotateArray[left];
    }
};

No7 斐波那契数列

斐波那契数列_牛客网

题目描述

image-20220805121847970

解题思路

class Solution {
public:
    int Fibonacci(int n) {
        if(n == 1 || n == 2)
            return 1;
        if(n == 3) 
            return 2;
        // 可以直接使用三个元素的容器进行轮换存放即可
        vector<int> nums(3);
        nums[0] = 1;
        nums[1] = 1;
        nums[2] = 2;
        // 需要第几项 就直接算到第几项
        for(int i = 3; i < n; i++){
            nums[i % 3] = nums[(i - 1) % 3] + nums[(i - 2) % 3];
        }
        return nums[(n - 1) % 3];
    }
};

No8 跳台阶

跳台阶_牛客网

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

解题思路

找规律,和斐波那契数列解法一致

f(1) = 1;

f(2) = 2;

f(3) = 3;

f(4) = 5;

f(n) = f(n - 1) + f(n - 2);

class Solution {
public:
    int jumpFloor(int number) {
        if(number <= 0) return 0;
        if(number == 1) return 1;
        if(number == 2) return 2;
        
        vector<int> nums(3);
        nums[0] = 1;
        nums[1] = 2;      
        
        for(int i = 2; i <= number; i++){
            nums[i % 3] = nums[(i - 1) % 3] + nums[(i - 2) % 3];
        }
        return nums[(number - 1) % 3];
    }
};

No9 跳台阶扩展版

牛客网原题链接

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

解题思路

讲解豁然开朗:因为n级台阶,第一步有n种跳法:跳1级、跳2级、到跳n级 跳1级,剩下n-1级,则剩下跳法是f(n-1) 跳2级,剩下n-2级,则剩下跳法是f(n-2) 所以f(n)=f(n-1)+f(n-2)+...+f(1) 因为f(n-1)=f(n-2)+f(n-3)+...+f(1) 所以f(n)=2*f(n-1)

递归算法:

class Solution {
public:
    int jumpFloorII(int number) {
        if(number == 1)
            return 1;
        // f(n) = 2*f(n-1)
        return 2 * jumpFloorII(number -1);
    }
};

No10 矩阵覆盖

矩形覆盖_牛客网 (nowcoder.com)

题目描述

我们可以用 2*1 的小矩形横着或者竖着去覆盖更大的矩形。请问用 n 个 2*1 的小矩形无重叠地覆盖一个 2*n 的大矩形,从同一个方向看总共有多少种不同的方法?

image-20220805223611954

解题思路

动态规划算法的基本思想是:将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解;对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解。动态规划算法将问题的解决方案视为一系列决策的结果。

对于斐波那契数列的递推公式:f(n) = f(n−1) + f(n−2); 除了自顶向下递归求解,还可以直接自底向上相加,递归的本质是从顶部往下找,然后再向上相加,我们可以使用动态规划直接相加。

dp[1] = 1;
dp[2] = 2;
for(int i = 3; i <= number; i++){
    dp[i] = dp[i - 1] + dp[i - 2];
}

但是这个方法使用了dp数组,空间复杂度为O(n),我们还可以对空间优化一下:注意到每次循环只使用到了第i−1个变量和第i−2个变量,那我们可以用两个变量不断滚动来优化。

class Solution {
public:
    int rectCover(int number) {
        if(number == 0) return 0;
        if(number == 1) return 1;
        if(number == 2) return 2;
        
        int dp1 = 1;
        int dp2 = 2;
        int res = 0;
        for(int i = 3; i <= number; i++){
            res = dp1 + dp2;
            // 更新变量,将2放入1,将res放入2
            dp1 = dp2;
            dp2 = res;           
        }
        return res;              
    }
};

No11 二进制中1的个数

二进制中1的个数_牛客网 (nowcoder.com)

题目描述

输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。

解题思路

将移位后的1与数字进行位与运算,结果为1就记录一次。

class Solution {
public:
    int NumberOf1(int n) {
        int res = 0;
        //遍历32位
        for (int i = 0; i < 32; i++) {
            //将移位后的1与原数值按位比较
            if ((n & (1 << i)) != 0)
                res++;
        }
        return res;
    }
};

牛客大神做法:如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。

举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。

这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。

class Solution{
public:
    int NumberOf1(int n){
        int res = 0;
        while(n != 0){
            n = n & (n - 1);
            res++;
        }
    }
};

No12 数值的整数次方

数值的整数次方 牛客网 (nowcoder.com)

题目描述

  • 求一个浮点数的整数次方
  • 整数有正有负
  • 不可以使用库函数,也不需要判断大数问题

解题思路

直接循环相乘即可,注意次方小于0 的情况,转换成 x的-2次为(1/x)的2次方。

class Solution {
public:
    double Power(double base, int exponent) {
        double res = 1;
        if (exponent < 0) {
            base = 1 / base;
            exponent = -exponent;
        }
        for (int i = 0; i < exponent; i++) {
            res *= base;
        }
        return res;
    }
};

快速幂算法

class Solution {
public: 
	double myPow(double base, int exponent) {
        if (exponent == 0)
            return 1;
        if (base == 0.0)
            return 0;
        long N = exponent;
        if (exponent < 0)
            N = -exponent;

        double res = 1.0;
        while (N > 0) {
            if (N % 2 != 0)
                // 为奇次幂就需要补充一个x
                res *= base;
            base *= base;    // 将得到的次幂相乘
            N >>= 1;         // 即N/2
        }
        return exponent < 0 ? 1 / res : res;
    }
};

No13 调整数组顺序使奇数位于偶数前面

调整数组顺序使奇数位于偶数前面_牛客网

题目描述

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

解题思路

暴力解法,新开辟一个数组保存数据

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        vector<int> arr;
        for(const int v : array){
            if(v & 1)
                arr.push_back(v);
        }
        for(const int v : array){
            if(!(v & 1))
                arr.push_back(v);
        }
        copy(arr.begin(), arr.end(), array.begin());
    }
};

No14 链表中倒数第k个结点

链表中倒数第k个结点_牛客网

题目描述

输入一个链表,输出该链表中倒数第k个结点。

解题思路

输出倒数第k个结点就是输出正数第n-k个结点,先遍历计节点数,再遍历计数第n-k个,注意0结点链表和k>n的情况

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(!pListHead || k <= 0)
            return nullptr;
        int n = 0;
        ListNode * cur = pListHead;
        while(cur){
            cur = cur->next;
            ++n;
        }
        if(n < k)
            return nullptr;
        n = n - k;
        while(n--){
            pListHead = pListHead->next;
        }
        return pListHead;
    }
};

解法2:快慢指针

使用快慢指针,首先让快指针先行k步,然后让快慢指针每次同行一步,直到快指针指向空节点,慢指针就是倒数第K个节点。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(!pListHead || k <= 0)
            return nullptr;
        auto slow = pListHead, fast = pListHead;
        while(k--){
            if(fast)
                fast = fast->next;
            else
                // 如果k > n 即fast->nullprt;
                return nullptr;
        }
        
        while(fast){
            fast = fast->next;
            slow = slow->next;
        }
        return slow;        
    }
};

No15 反转链表

反转链表_牛客网 (nowcoder.com)

题目描述

给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。

数据范围:0≤n≤1000

img

解题思路

解法1:先对原链表做头删操作,再对新链表做头插

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) : val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(!pHead)
            return nullptr;
        ListNode * newHead = nullptr;
        ListNode * node = nullptr;
        while(pHead){
            // 原链表头删
            // 保存当前节点
            // 头节点后移
            node = pHead; 
            pHead = pHead->next; // 先将head指向下一个,因为等下会改变原head的指向
            // 新链表头插
            // 指向新的头节点
            // 头节点后移
            node->next = newHead; // 注意使用node来切换指向
            newHead = node;
        }
        return newHead;
    }
};

解法2:使用三个节点不断移位

【图文解析】反转一个单链表

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(!pHead)
            return nullptr;
        ListNode * p0 = nullptr;
        ListNode * p1 = pHead;
        ListNode * p2 = pHead->next;
        
        while(p1){
            p1->next = p0;
            p0 = p1;
            p1 = p2;
            if(p2)
               p2 = p2->next;          
        }
        return p0;
    }
};

原理同上,只是新增加一个局部变量,代替了原来的p2指针

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        ListNode * cur = pHead;
        ListNode * pre = NULL;
        while(cur){
            ListNode * temp;
            temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

No16 合并两个有序链表

合并两个排序的链表_牛客网 (nowcoder.com)

题目描述

输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。

解题思路

初始化:定义cur指向新链表的头结点
操作:

  1. 如果l1指向的结点值小于等于l2指向的结点值,则将l1指向的结点值链接到cur的next指针,然后l1指向下一个结点值
  2. 否则,让l2指向下一个结点值
  3. 循环步骤1,2,直到l1或者l2为nullptr
  4. 将l1或者l2剩下的部分链接到cur的后面技巧

技巧

一般创建单链表,都会设一个虚拟头结点,也叫哨兵,因为这样每一个结点都有一个前驱结点。

迭代版本求解

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        ListNode * vhead = new ListNode(-1);
        ListNode * cur = vhead;
        while(pHead1 && pHead2){
            if(pHead1->val <= pHead2->val){
                cur->next = pHead1;
                pHead1 = pHead1->next;
            }
            else{
                cur->next = pHead2;
                pHead2 = pHead2->next;
            }
            cur = cur->next;
        }
        cur->next = pHead1 ? pHead1 : pHead2;
        return vhead->next;
    }
};

递归版本求解

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        if(!pHead1) return pHead2;
        if(!pHead2) return pHead1;
    	if(pHead1->val <= pHead2->val){
            pHead1->next = Merge(pHead1->next, pHead2);
            return pHead1;
        }
        else{
            pHead2->next = Merge(pHead1, pHead2->next);
            return pHead2;
        }
    }
};

No17 树的子结构

树的子结构_牛客网 (nowcoder.com)

题目描述

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

解题思路

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
        //如果A是空树 或者 B是空树,直接返回false
        if(!pRoot1 || !pRoot2)
            return false;
        // A的根节点和B的根节点相同,依次比较他的子节点
        bool flag1 = isSub(pRoot1, pRoot2);
        // 判断B是否是 A左子树的子结构
        bool flag2 = HasSubtree(pRoot1->left, pRoot2);
        // 判断B是否是 A右子树的子结构
        bool flag3 = HasSubtree(pRoot1->right, pRoot2);
        // 最终返回值
        return flag1 || flag2 || flag3;
    }
    bool isSub(TreeNode* A, TreeNode* B){
        // 迭代遍历完B时,说明B和A匹配
        if(B == nullptr)
            return true;
        // 若此时B不为空,A为空表示不匹配
        if(A == nullptr)
            return false;
        // 若A与B不相等,直接返回false
        if(A->val != B->val)
            return false;
        // 如果A节点与B节点相等,迭代判断A B子树
        return isSub(A->left, B->left) && isSub(A->right, B->right);    
    }
};

代码优化:

class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
        //如果A是空树 或者 B是空树,直接返回false
        if(!pRoot1 || !pRoot2)
            return false;
        // A的根节点和B的根节点相同,依次比较他的子节点
        // 判断B是否是 A左子树的子结构
        // 判断B是否是 A右子树的子结构
        // 最终返回值
        return isSub(pRoot1, pRoot2) || HasSubtree(pRoot1->left, pRoot2) || HasSubtree(pRoot1->right, pRoot2);
    }
    bool isSub(TreeNode* A, TreeNode* B){
        // 迭代遍历完B时,说明B和A匹配
        if(B == nullptr)
            return true;
        // 若此时B不为空,A为空表示不匹配
        if(A == nullptr)
            return false;
        // 若A与B不相等,直接返回false
        if(A->val != B->val)
            return false;
        // 如果A节点与B节点相等,迭代判断A B子树
        return isSub(A->left, B->left) && isSub(A->right, B->right);    
    }
};

No22 从上往下打印二叉树

从上往下打印二叉树_牛客网 (nowcoder.com)

题目描述

不分行从上往下打印出二叉树的每个节点,同层节点从左至右打印。例如输入{8,6,10,#,#,2,1},如以下图中的示例二叉树,则依次打印8,6,10,2,1(空节点不打印,跳过),请你将打印的结果存放到一个数组里面,返回。

解题思路

知识点:队列

队列是一种仅支持在表尾进行插入操作、在表头进行删除操作的线性表,插入端称为队尾删除端称为队首,因整体类似排队的队伍而得名。它满足先进先出的性质,元素入队即将新元素加在队列的尾,元素出队即将队首元素取出,它后一个作为新的队首。

思路:

二叉树的层次遍历就是按照从上到下每行,然后每行中从左到右依次遍历,得到的二叉树的元素值。对于层次遍历,我们通常会使用队列来辅助:

因为队列是一种先进先出的数据结构,我们依照它的性质,如果从左到右访问完一行节点,并在访问的时候依次把它们的子节点加入队列,那么它们的子节点也是从左到右的次序,且排在本行节点的后面,因此队列中出现的顺序正好也是从左到右,正好符合层次遍历的特点。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {	}
};*/
class Solution {
public:
    vector<int> PrintFromTopToBottom(TreeNode* root) {
		vector<int> res;
        if(root == nullptr)
            return res;
        queue<TreeNode*> q;
        q.push(root);
        auto cur = root;
        while(!q.empty()){
            cur = q.front();
            res.push_back(cur->val);
            q.pop();
            if(cur->left)
                q.push(cur->left);
            if(cur->right)
                q.push(cur->right);
        }
        return res;
    }
};
posted @   Happinesspill  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
点击右上角即可分享
微信分享提示