给定一个包含红色、白色和蓝色,一共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;
}
}
给定一组不含重复元素的整数数组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;
}
};
给定一个二维网格和一个单词,找出该单词是否存在于网格中。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
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;
}
}
给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:
思路:
中序遍历的结果一定是升序的
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;
}
}