102.二叉树的层序遍历
运用队列的性质,来进行遍历。
初始化队列(把跟节点放到队列里),队列里有几个元素就内循环(内循环的循环次数就是某层有多少个)几次,把同层的每一个元素都访问到,之后把val放到数组里,判断left和right是否为空,不是空继续放到队列里。当队列的元素为0时外循环结束(外循环其实就是层数)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> list =new ArrayList<>();
if(root==null) return list; //防止root为空,下面报错
Queue<TreeNode> queue=new ArrayDeque<>();
queue.offer(root); //队列初始化
while(queue.size()!=0){
int size=queue.size();
List<Integer> integerList =new ArrayList<>();
for(int i=0;i<size;i++){
TreeNode treeNode=queue.poll();
integerList.add(treeNode.val);
if(treeNode.left!=null) queue.offer(treeNode.left);
if(treeNode.right!=null) queue.offer(treeNode.right);
}
list.add(integerList);
}
return list;
}
}
用栈实现队列
import java.util.Stack;
public class MyQueue {
Stack<Integer> stackIn;
Stack<Integer> stackOut;
public MyQueue() {
stackIn = new Stack<>();
stackOut = new Stack<>();
}
//放进来一个
public void push(int x) {
stackIn.push(x);
}
//拿出来
public int pop() {
while (!stackIn.empty()) {
stackOut.push(stackIn.pop());
}
int i = stackOut.pop();
while (!stackOut.empty()) {
stackIn.push(stackOut.pop());
}
return i;
}
//查看要拿出来的,但不拿出来
public int peek() {
while (!stackIn.empty()) {
stackOut.push(stackIn.pop());
}
int i = stackOut.peek();
while (!stackOut.empty()) {
stackIn.push(stackOut.pop());
}
return i;
}
//检查是否为空
public boolean empty() {
return stackIn.empty();
}
}
98.验证二叉搜索树
设树的每一个节点都可以找出来最大和最小值,没有最大值或最小值的就存null(根节点就都是null)。由此条件看代码,画一画即可明白。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isValidBST(TreeNode root) {
return test(root, null, null);
}
public boolean test(TreeNode root, Integer lower, Integer upper) {
if (root == null) {
return true;
}
int val = root.val;
if (lower != null && lower >= val) return false;
if (upper != null && upper <= val) return false;
if(!test(root.left,lower,val)) return false;
if(!test(root.right,val,upper)) return false;
return true;
}
}
349.两个数组的交集
原题
利用哈希表的原理,题目0 <= nums1[i], nums2[i] <= 1000所以我创建了一个有1001个空间的数组,但其实可以用HashSet来应对更多场景。
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Integer[] array=new Integer[1001];
ArrayList<Integer> arrayList=new ArrayList<>();
for (int i : nums1) {
array[i]=1;
}
for (int i : nums2) {
if(array[i]!=null){
arrayList.add(i);
array[i]=null;
}
}
int[] arr=arrayList.stream()
.mapToInt(Integer::intValue)
.toArray();
return arr;
}
}
1.两数之和
用两数的和减去当前的遍历到的数即可得到需要的另外一个数,再在map里get如果get的结果不为null,即代表可以返回数组了,如果为null则把当前数存入map中
class Solution {
public int[] twoSum(int[] nums, int target) {
Map map=new HashMap<Integer,Integer>();
for(int i=0;i<nums.length;i++){
int num=target-nums[i];
Integer index=(Integer)map.get(num);
if(index!=null){
int [] arr={i,index};
return arr;
}
map.put(nums[i],i);
}
return null;
}
}
18.四数之和
首先把这个数组进行排序,从小到大。 固定两个数,在用另外两个对撞。四数和如果等于target则加入进lists集合里,如果小于target让left++,如果大于target让right–。这里最复杂的是如何进行去重复(看代码)。之后还有一点要注意的是,sum有可能会大于Integer.MAX_VALUE所以sum用long类型!!!
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> lists = new ArrayList<>();
if (nums.length < 4) return lists;
for (int i = 0; i < nums.length - 1; i++) {
if (i != 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < nums.length; j++) {
if (j != i + 1 && nums[j] == nums[j - 1]) continue;
int left = j + 1;
int right = nums.length - 1;
while (left < right) {
long sum = (long)nums[i] + (long)nums[j] + (long)nums[left] + (long)nums[right];
if (sum > target) right--;
else if (sum < target) left++;
else {
lists.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
left++;
right--;
}
}
}
}
return lists;
}
}
76.最小覆盖字串
这个运用到滑动窗口的思想,该解题思路里最重要的是用来记录符合要求的数量conform 我第一遍写好之后遇到的三个问题:
- while循环里的left一定要++因为这时候已经有合适的字符串了可以试着从左边缩减窗口,看看能不能达到要求,不要–要不然会出现超出索引异常(我第一遍写的时候没注意到这个问题)
- 记录最小的子串初始值一定要用一个特别大的数最好是Integer.MAX_VALUE,如果用0的话还得单独去判断
- while里的条件一定是左指针<=右指针,这样是防止t为一个字符
class Solution {
public String minWindow(String s, String t) {
//返回字符的索引
int start=0;
int end=0;
Map<Character, Integer> map = new HashMap<>();
for (char c : t.toCharArray()) {
Integer integer = map.get(c) == null ? 1 : map.get(c) + 1;
map.put(c, integer);
}
//窗口里符合要求的字符
Map<Character, Integer> windows = new HashMap<>();
//记录符合了几个字符
int conform = 0;
//记录最短长度 2.这里长度取极限取0的话就坏了
int length = Integer.MAX_VALUE;
//滑动窗口的左指针
int left = 0;
//字符串s的char[]
char[] sArray = s.toCharArray();
//这里的i相当于右指针
for (int i = 0; i < sArray.length; i++) {
char c = sArray[i];
if (map.get(c) == null) {
continue;
}
Integer integer = windows.get(c) == null ? 0 : windows.get(c);
if (map.get(c) > integer) {
if (map.get(c) <= integer + 1) {
conform++;
}
}
windows.put(c, integer + 1);
//3.左右指针可以相等
while (left <= i) {
if (map.size() == conform) {
int size = i - left + 1;
if (size < length) {
start=left;
end=i+1;
length = size;
}
Integer a = windows.get(sArray[left]);
if (a != null) {
a = a - 1;
windows.put(sArray[left], a);
if (map.get(sArray[left]) > a)
conform--;
}
//1.这里是往右走别--了
left++;
} else {
break;
}
}
}
return s.substring(start,end);
}
}
1456.定长子串中元音的最大数目
我第一次写的时候,每循环一次就重新判断有多少个是符合的,导致超出时间限制,才有的如下一版
class Solution {
public int maxVowels(String s, int k) {
int size = 0;
char[] chars = s.toCharArray();
int[] array = new int[128];
array['a'] = 1;
array['e'] = 1;
array['i'] = 1;
array['o'] = 1;
array['u'] = 1;
//int left = 0; 由i-k代替left
for (int i = 0; i < k; i++) {
if (array[chars[i]] == 1) {
size++;
}
}
int length = size;
for (int i = k; i < chars.length; i++) {
if (array[chars[i-k]] == 1) length--;
//left++;
if (array[chars[i]] == 1) length++;
if (size < length) size = length;
}
return size;
}
}
136.只出现一次的数字
这道题真是巧妙地运用了位运算符异或(^)的特性,我自己也是把吝啬发挥到了极致,能不弄新的空间就不弄。
class Solution {
public int singleNumber(int[] nums) {
for (int i = 1; i < nums.length; i++) {
nums[0]^=nums[i];
}
return nums[0];
}
}