leetcode题解日练--2016.6.24

编程日记,尽量保证每天至少3道leetcode题,仅此记录学习的一些题目答案与思路,尽量用多种思路来分析解决问题,不足之处还望指出。标红题为之后还需要再看的题目。

今日题目:1、求二叉树和为sum的路径;2、判断数组是否合法;3、求二叉树的最小深度。

26. 112. Path Sum | Difficulty: Easy

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.

For example:
Given the below binary tree and sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.
题意:给定一棵二叉树与一个sum值,求一条从根节点到叶节点的路径。
思路:
1、很容易用递归的思想去思考这个问题,递归的话当然就是找终止条件了。失败的终止条件是root为NULL,而成功找到的终止条件是root节点的值恰好是sum剩下的值并且左右均无子节点。当前既不成功也不失败就递归去判断这个点的左节点和右节点是否有一个满足,注意此时sum应该减去root->val的值。
代码:
递归版

/**
 * 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 hasPathSum(TreeNode* root, int sum) {
        if(root==NULL )    return false;
        if(root->val==sum && root->left==NULL && root->right==NULL) return true;
        return hasPathSum(root->left,sum-root->val)||hasPathSum(root->right,sum-root->val);
    }
};

结果:12ms
2、将上述递归版本改为迭代版本。先将最左路的元素加入到一个栈中,如果不满足依次去访问这个栈中的元素的右子路径,访问右路径的策略是先将右路的最左路加入,然后和之前的步骤一样。

class Solution {
public:
    bool hasPathSum(TreeNode *root, int sum) {
        //后序遍历
        stack<TreeNode *> s;
        //pre节点表示当前节点的上一个节点,为空代表当前节点是第一个节点,没有上一个节点
        TreeNode *pre = NULL, *cur = root;
        int SUM = 0;
        //首先将cur设置为当前树的最左路节点
        while (cur || !s.empty()) {
            while (cur) {
                s.push(cur);
                SUM += cur->val;
                cur = cur->left;
            }
            cur = s.top();
            //如果此时在cur已经满足了路径和为sum并且无左右节点的条件,则返回为真
            if (cur->left == NULL && cur->right == NULL && SUM == sum) {
                return true;
            }
            //如果当前节点有右节点并且它的右节点并没有访问过,那么就去访问cur的右节点
            if (cur->right && pre != cur->right) {
                cur = cur->right;
            //如果右节点访问过了或者当前节点并没有右节点
            } else {
                pre = cur;
                s.pop();
                SUM -= cur->val;
                cur = NULL;
            }
        }
        return false;
    }
};

结果:15ms,为什么时间反而更多?
这段代码还不熟悉,之后还需要再看。

36. Valid Sudoku | Difficulty: Easy

Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.

The Sudoku board could be partially filled, where empty cells are filled with the character ‘.’.
题意:验证一个数独是否有效,有效不代表有解,只要填充部分不冲突即视为有效。什么是冲突?就是每一行、每一列、每一个小方格只能包含1-9各一个。
思路:
1、依次判断每一行、每一列、每一方格的元素是否合法
c++

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
       int cnt[9] = {0};
        //首先判断每行
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {   
                if(board[i][j]=='.')
                    continue;
                cnt[(int)(board[i][j]-'1')]++;
            }
            for (int idx = 0;idx<9;idx++)
            {
                if (cnt[idx]>1)
                    return false;
                else
                    cnt[idx]=0;
            }
        }
        //再判断每列
         for(int j=0;j<9;j++)
        {
            for(int i=0;i<9;i++)
            {   
                if(board[i][j]=='.')
                    continue;
                  cnt[(int)(board[i][j]-'1')] ++;
            }
             for (int idx = 0;idx<9;idx++)
            {
                if (cnt[idx]>1)
                    return false;
                else
                    cnt[idx]=0;
            }
        }
        //判断每一个小格子
        for(int k=0;k<9;k++)
        {
            for(int i=3*(k/3);i<3*(k/3)+3;i++)
            {   
                for(int j=3*(k%3);j<3*(k%3)+3;j++)
                {
                if(board[i][j]=='.')
                    continue;
                 cnt[(int)(board[i][j]-'1')] ++;
                }
            }
           for (int idx = 0;idx<9;idx++)
            {
                if (cnt[idx]>1)
                    return false;
                else
                    cnt[idx]=0;
            }
        }
        return true;
    }
};

结果:16ms

2、创建三个数组用来保存状态,一个储存行信息,一个储存列信息,一个储存块信息。
rows[i][j] 是指的数字(j+1)在第i行出现的次数
cols[i][j] 是指的数字(j+1)在第i行出现的次数
blocks[i][j][k]是指的数字(k+1)在第(i,j)个小块中出现的次数

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {

    int rows[9][9]={0}; //rows[i][j] 是指的数字(j+1)在第i行出现的次数
    int cols[9][9]={0}; //cols[i][j] 是指的数字(j+1)在第i行出现的次数
    int blocks[3][3][9]={0};//blocks[i][j][k]是指的数字(k+1)在第(i,j)个小块中出现的次数
    for(int row=0;row<9;row++)    //row代表行,col代表列,遍历一次
        for(int col=0;col<9;col++)
            if(board[row][col]!='.'){   //跳过'.'
                int number=board[row][col]-'1'; //将字符转换位数字0-8
                if(rows[row][number]++) return false; //如果数字number在第row行第二次出现
                if(cols[col][number]++) return false;//如果数字number在第col列第二次出现
                if(blocks[row/3][col/3][number]++) return false;//如果数字number在第(row/3,col/3)个小块第二次出现
            }
    return true;

    }
};

111. Minimum Depth of Binary Tree | Difficulty: Easy

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

题意:求二叉树的最小深度,但是必须是从根节点到叶节点,不能是根节点直接到空节点。
思路:与最大深度类似,最小深度只要再多加一次判断子树是否为空就可以写出递归版本的代码。
代码:
C++

/**
 * 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:
    int minDepth(TreeNode *root) {
        if(!root) return 0;
        if(!root->left) return 1 + minDepth(root->right);
        if(!root->right) return 1 + minDepth(root->left);
        return 1+min(minDepth(root->left),minDepth(root->right));
    }
};

结果:12ms

2、BFS的思想,从根节点开始判断,逐层进行判断,一但满足该节点是叶子节点返回当前节点的深度。
c++

class Solution {
public:
    int minDepth(TreeNode *root) {
        if (root==NULL) return 0;
        queue <TreeNode*> nodes;
        TreeNode* tmp;
        nodes.push(root);
        int depth = 0;
        while(!nodes.empty())
        {
            depth++;
            int size = nodes.size();
            for(int i=0;i<size;i++)
            {
                tmp = nodes.front();
                if(tmp->left==NULL && tmp->right==NULL)    return depth;
                if(tmp->left) nodes.push(tmp->left);
                if(tmp->right) nodes.push(tmp->right);
                nodes.pop();
            }
        }
     return 0;  
    }
};

结果:12ms

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值