Leetcode每天五题-05

  1. 颜色分类

给定一个包含红色、白色和蓝色,一共n个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

进阶:

一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?

思路:

扫描数组,将0移动到前面,2移动到后面,1会自动排到中间

class Solution {
    public void sortColors(int[] nums) {
        if(nums == null || nums.length == 0){
            return ;
        }
        int left=0,right=nums.length-1;
        //<=,因为right是后减
        for(int i = 0;i<=right;){
            if(nums[i] == 0){
                //i可以且必须自增,因为是将前面的交换到后面去,接下来会处理到
                swap(nums,left++,i++);
            }else if(nums[i] == 2){
                //i不能增,还要考察交换过来的是什么数
                swap(nums,right--,i);
            }else{
                i++;
            }
        }
    }
    public void swap(int[] nums,int a,int b){
        int tmp;
        tmp = nums[a];
        nums[a] = nums[b];
        nums[b] = tmp;
    }
}
  1. 子集

给定一组不含重复元素的整数数组nums,返回该数组所有可能的子集(幂集)。

说明:

解集不能包含重复的子集。

思路:

通过2^n二进制0和1的情况来表示是否加对应的元素

class Solution {
public List<List<Integer>> subsets(int[] nums) {

    if(nums == null || nums.length == 0){
        return null;
    } 
	int n = 1 << nums.length;
	List<List<Integer>> ans = new ArrayList<>();
	for (int i = 0; i < n; i++) {
		char[] bits = Integer.toBinaryString(i).toCharArray();
		List<Integer> tmp = new ArrayList<>();
		for (int k = 0; k < bits.length; k++) {
			if (bits[k] == '1') {
			    //注意对应关系
				tmp.add(nums[nums.length - bits.length + k]);
			}
		}
		ans.add(tmp);
	}
	return ans;
  }
}

讨论区版本

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> ret;
        ret.push_back({});
        int size=nums.size();
        int subsize=pow(2,size);
        int hash=1;
        while(hash<subsize){
            vector<int> temp;
            for(int k=0;k<size;k++) {
                int a=1<<k;
                if(a&hash) {
                    temp.push_back(nums[k]);
                }
            }
            ret.push_back(temp);
            hash++;
        }
        return ret;
    }
};
  1. 单词搜索

给定一个二维网格和一个单词,找出该单词是否存在于网格中。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例:

board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]

给定 word = “ABCCED”, 返回 true.
给定 word = “SEE”, 返回 true.
给定 word = “ABCB”, 返回 false.

class Solution {
	public boolean exist(char[][] board, String word) {
		// 首先找到首字母相同的位置,然后深搜。
		boolean visited[][] = new boolean[board.length][board[0].length];
		for (int i = 0; i < board.length; i++) {
			for (int j = 0; j < board[0].length; j++) {
				if (board[i][j] == word.charAt(0)) {
					if (isExist(visited, board, word, i, j, 0)) {
						return true;
					}
				}
			}
		}
		return false;
	}

	public boolean isExist(boolean visited[][], char[][] board, String word, int x, int y, int index) {
		// 如果已经比较完,返回true
		if (index == word.length()) {
			return true;
		}
		// 如果越界|点已访问|比较的位置不相等,返回false
		else if (x < 0 || x >= board.length || y < 0 || y >= board[0].length || visited[x][y]
				|| board[x][y] != word.charAt(index)) {
			return false;
		} else {
			// 标记当前点为访问
			visited[x][y] = true;
			// 往上下左右四个方向尝试
			boolean exist = (isExist(visited, board, word, x + 1, y, index + 1)
					|| isExist(visited, board, word, x, y + 1, index + 1)
					|| isExist(visited, board, word, x - 1, y, index + 1)
					|| isExist(visited, board, word, x, y - 1, index + 1)) ? true : false;

			visited[x][y] = false;
			return exist;

		}
	}
}

94.二叉树的中序遍历

进阶: 递归算法很简单,你可以通过迭代算法完成吗?
思路:

将左边界不断压栈,直到为null,这时从栈中弹出一个元素,令cur = node.right 继续这一过程

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> ans = new ArrayList<Integer>();
        if(root == null){
            return ans;
        }
        TreeNode cur = root;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while(stack.size() != 0 || cur != null){
            while(cur!=null){
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode node = stack.pop();
            ans.add(node.val);
            cur = node.right;
        }
        return ans;
    }
}
  1. 验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

思路:

中序遍历的结果一定是升序的

class Solution {
    public boolean isValidBST(TreeNode root) {
        List<Integer> inorder = inorderTraversal(root);
        if(inorder.size() == 0){
            return true;
        }
        for(int i = 1;i < inorder.size();i++){
            if(inorder.get(i) <= inorder.get(i-1)){
                return false;
            }
        }
        return true;
    }
}

讨论区答案:

class Solution {
    double last = -Double.MAX_VALUE;
    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }
        if (isValidBST(root.left)) {
            if (last < root.val) {
                last = root.val;
                return isValidBST(root.right);
            }
        }
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值