数据结构入门
第一天内容:
第一题,存在重复元素
这一道题的思路是通过前一个的length()和它用hashSet存储之后的length()的结果进行对比,如果相等,说明了一件事情,这个里面不包含重复元素,如果不相等说明,有重复元素
具体代码如下:
class Solution {
public boolean containsDuplicate(int[] nums) {
//分析题目:
//首先如果全部不相同,返回false
//而只要出现了一个值拥有两个或两个以上返回true
//两个for循环不能通过
Set<Integer> Set = new HashSet<Integer>();
for(int i:nums) {
Set.add(i);
}
return Set.size()<nums.length?true:false;
}
}
第二题,最大子数组和
分析,它需要的是求和,求和需要满足 的条件,他的结果必须得是一个正数,它不能加着加着变成了负数,所以可以判断一个条件,如果这个值的和已经开始变成负数了,就开始进行下一个。所以我们可以使用递归的方法来进行求和的操作。
代码段
class Solution {
public int maxSubArray(int[] nums) {
int res = nums[0];//第一个值
int sum = 0;//求和设置的一个变量
for(int num: nums) {//遍历的方式
if(sum >0) {//首先要保证前面的和是大于0的
//原因是因为这个sum的值不可能是小于0的
sum +=num;
}else{
sum = num;//新的开始
}
res = Math.max(res,sum);//比较最大值
/**
比较一下值,最后确定所得到的值的大小,和上一个记录的sum的值进行比较,得到结果。
*/
}
return res;
}
}
第二天内容
第一题,两数之和
两种方法:
第一种:暴力破解
第二种:用HashMap的方法:containKey
class Solution {
public int[] twoSum(int[] nums, int target) {
// int i;
// int [] num = new int[2];
//用的是暴力破解法
/* for(int j= 0;j<nums.length-1;j++) {
for(int z=j+1;z<=nums.length-1;z++) {
if(nums[j]+nums[z] == target) {
num[0] = j;
num[1] = z;
return num;
}
}
}*/
//时间复杂度变小的方法,哈希数
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i< nums.length; i++) {
if(map.containsKey(target - nums[i])) {
return new int[] {map.get(target-nums[i]),i};
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
}
第二题,合并两个有序数组
, 分析:
两个有序数组合并之后,还是以递归的方式。所以可以先比较每一个数组的第一个值,谁小谁就第一位,之后再进行下一位和上一个没有进新的数组的里面的哪一个
代码段
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
//首先明白两个非递减顺序合并的是一个新的非递减顺序,说明合成的是一个递增的序列
int i = m - 1, j = n - 1, k = m + n - 1;
while (j >= 0) {
if (i < 0 || nums2[j] > nums1[i]) {
nums1[k--] = nums2[j--];
} else {
nums1[k--] = nums1[i--];
}
// nums1[k--]=nums2[j]>nums1[i]||i<0?nums2[j--]:nums1[i--];
}
}
}
第三题 ,整数反转。
分析;就是将数字倒过来。,如果是负数,先把负号放在最前面,再进行反转
代码段
class Solution {
public int reverse(int x) {
if(x==0) {
return 0;
}
int y=x>0?x:-x;//此时y代表的值是x的绝对值;
int num;
int res=0;
while(y!=0) {
num = y%10;//最尾部的数
int temp = res;
res = res*10 + num;
y = y/10;
if(res/10!=temp) {
return 0;
}
}
return x>0?res:-res;
}
}
第三天内容
第一题,两个数组的交集
分析题目可以知道,这道题所要求的是两个数组中里面一样的值,将它弄在新的数组里面。
代码段
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
if(nums1.length>nums2.length) {
return intersect(nums2 , nums1);
}
int [] jieguo = new int [nums1.length];
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int num : nums1) {
int count = map.getOrDefault(num, 0) + 1;
map.put(num, count);
}
int index = 0;
for (int num : nums2) {
int count = map.getOrDefault(num, 0);
if (count > 0) {
jieguo[index] = num;
index++;
count--;
if (count > 0) {
map.put(num, count);
} else {
map.remove(num);
}
}
}
return Arrays.copyOfRange(jieguo, 0, index);
}
}
第二题,买卖股票的最佳时机
首先要确定的一件事情,就是它所买的时候的价格一定要比卖的时候低
代码段
class Solution {
public int maxProfit(int[] prices) {
if(prices.length<=1) {
return 0;
}
int min=prices[0],max=0;
for(int i=1;i<prices.length;i++) {
//max = Math.max(max, prices[i] - min);
max = max>(prices[i]-min)?max:prices[i]-min;
// min = Math.min(min, prices[i]);
min=min>prices[i]?prices[i]:min;
}
return max;
}
}
第四天内容
第一题,重塑矩阵
分析:
首先:第一步需要判断矩阵的元素有没有变化。
再进行输出
代码段:
class Solution {
public int[][] matrixReshape(int[][] mat, int r, int c) {
int m = mat.length;
int n = mat[0].length;
if (m * n != r * c) {
return mat;
}
int[][] ans = new int[r][c];
for (int x = 0; x < m * n; ++x) {
ans[x/c][x%c]=mat[x / n][x % n];
}
return ans;
}
}
第二题,杨辉三角
分析:
把图形分解一下
1
11
121
1331
14641
....
可以得到一个结论
它的第一行的数都是1
每一行最后一个都是1
每一个中间的值,都等于上一行的和这这一列相同的位置,和前一个位置的和
代码段:
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> list = new ArrayList<>();
int[][] arr = new int [numRows][numRows];
for(int i=0;i<numRows;i++) {
List<Integer> zhongjian = new ArrayList<>();
for(int j=0;j<=i;j++) {
if(j==0||j==i) {
arr[i][j]=1;
}else{
arr[i][j]=arr[i-1][j-1]+arr[i-1][j];
}
zhongjian.add(arr[i][j]);
}
list.add(zhongjian);
}
return list;
}
}
第五天
第一题,有效的数独
分析:
用HashSet,因为HashSet不能存储相同的元素。
代码段
class Solution {
public boolean isValidSudoku(char[][] board) {
Set<Character> row = new HashSet<>();
Set<Character> col = new HashSet<>();
Set<Character> jiugunge = new HashSet<>();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[j][i] != '.' && !row.add(board[j][i]))
return false;
if (board[i][j] != '.' && !col.add(board[i][j]))
return false;
if (board[i % 3 * 3 + j / 3][i / 3 * 3 + j % 3] != '.' && !jiugunge.add(board[i % 3 * 3 + j / 3][i / 3 * 3 + j % 3]))
return false;
}
row.clear();
col.clear();
jiugunge.clear();
}
return true;
}
}
第二题,矩阵清零
这一道题,我最开始的思路是正确的,但是就是做不出来,因为没有考虑到如果一次判断这一个为0那么这一行就为0的时候,当进行到下一行也会变成0,最后就会导致出现错误。出现整个数组全为0的情况。最后我实在想不出来了的时候,这个时候我就去看了一下参考答案。
它的思路就是,如果出现了将每一行每一列重新设置为一个Boolean类型,如果出现了为0的情况,就将该值返回为true,如果没有出现的话就返回false。最后执行到后面,再次做一个循环,如果它的行中满足某一个值为0,则哪一行的所有值都为0,同时为0的那个值,它所在的那一列也会变成都为0
class Solution {
public void setZeroes(int[][] matrix) {
// int[][] arr = new int[matrix.length][matrix[0].length];
// //这个函数记录的是matrix的包含0的数据;
// for(int i=0;i<matrix.length;i++) {//这里是执行的循环
// int m=0;
// int n=0;
// for(int j=0;j<matrix[0].length;j++) {
// if(matrix[i][j]==0){
// m=i;n=j;
// matrix[i][j]=arr[m][n]=0;
// }
// }
// }
// for(int i=0;i<matrix.length;i++) {//这里是执行的循环
// for(int j=0;j<matrix[0].length;j++) {
// if(arr[i][j]==0){
// arr[i][0]=0;
// arr[0][j]=0;
// }
// }
// }
// for(int i=0;i<matrix.length;i++) {//这里是执行的循环
// for(int j=0;j<matrix[0].length;j++) {
// if(arr[i][j]!=0){
// arr[i][j]=matrix[i][j];
// }
// }
// }
// for(int i=0;i<matrix.length;i++) {//这里是执行的循环
// for(int j=0;j<matrix[0].length;j++) {
// matrix[i][j]=arr[i][j];
// }
// }
int m = matrix.length, n = matrix[0].length;
boolean[] row = new boolean[m];
boolean[] col = new boolean[n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == 0) {
row[i] = col[j] = true;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (row[i] || col[j]) {
matrix[i][j] = 0;
}
}
}
}
}
第六天
第一题,赎金信
分析:
如果magazine中包含ransomNote里面的所有的元素,就会返回true,否则返回false;
最开始我是想用subString()这个方法的,但是后来才发现用这个方法会报错,我也不知道这是为什么,然后我就去看了答案,以为它也是用的subString方法,后来发现并不是,它用的是Ascll码的方式,我去看评论也没有看到有人用subString方法。由于看了答案,所以我就去用了它的源码了。
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
// int m= ransomNote.length();
// int n= magazine.length();
// if(m>n) {
// return false;
// }else{
// for(int i=1;i<n-m;i++) {
// if(ransomNote.equal(magazine.subString(i,m))){
// return true;
// }
// m++;
// }
// }
int[] arr = new int[26];
int temp;
for (int i = 0; i < magazine.length(); i++) {
temp = magazine.charAt(i) - 'a';
arr[temp]++;
}
for (int i = 0; i < ransomNote.length(); i++) {
temp = ransomNote.charAt(i) - 'a';
//对于金信中的每一个字符都在数组中查找
//找到相应位减一,否则找不到返回false
if (arr[temp] > 0) {
arr[temp]--;
} else {
return false;
}
}
return true;
}
}
第二题,有效的字母异位词
分析:异位词,说明它里面包含的字母是相同的
所以第一步,判断它们的字符长度是否相等,如果相等,就进行比较它们里面的字符是否是一致的。如果都有,说明了一件事情,说明了这个字符是字母异位词。
代码段:
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length()!=t.length()){
return false;
}else{
char[] str1 = s.toCharArray();
char[] str2 = t.toCharArray();
Arrays.sort(str1);
Arrays.sort(str2);
return Arrays.equals(str1, str2);
}
}
}
第七天
第一题,字符串的第一个唯一字符
分析:
如果出现了一个字符,里面全是AABB这样有重复的元素,就说明了它是一个重复的字符,此时就会返回-1,如果里面的字符是这种AACBB这样类似的题目。
代码段
class Solution {
public int firstUniqChar(String s) {
for(int i=0; i<s.length(); i++){
int first = s.indexOf(s.charAt(i));
int last = s.lastIndexOf(s.charAt(i));
if(first == last){
return i;
}
}
return -1;
}
}
第二题,环形链表
分析:题目中的第一句话中给出的如果链表中有某个节点,可以通过连续跟踪next指针再次到达
这道题最开始很难理解这个next的含义,后来我去看了一下它的答案,分析了一下,才想明白,它的含义就是
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
//注意里面有一个情况
Set<ListNode> set = new HashSet<ListNode>();
while(head!=null) {
if(!set.add(head.next)) {
return true;
}head = head.next;
}
return false;
}
}
第八天
第一题,合并两个有序数组
分析:
两个升序链表结合成新的一个,这个前面有一道类似的题
所以直接给代码段
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode prehead = new ListNode(-1);
ListNode prev = prehead;
while(list1!=null && list2!=null) {
if(list1.val<=list2.val) {
prev.next = list1;
list1=list1.next;
}else{
prev.next = list2;
list2=list2.next;
}
prev = prev.next;
}
prev.next = list1 == null ? list2 : list1;
return prehead.next;
}
}
第二题,移除链表元素
分析,只需要将里面中含有val的值的数变为null,可以直接得到结果。
代码段
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
// ListNode p =new ListNode(-1);
// while(head!=null) {
// if(head.val==val){
// p.next=head.next;
// head = head.next;
// }else{
// p.add(head.val);
// }
// }
// return p.next;
if (head == null) {
return head;
}
head.next = removeElements(head.next, val);
return head.val == val ? head.next : head;
}
}
第九天
第一题,反转链表
反转链表就是将原来的链表倒过来,
代码段
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null; //前指针节点
ListNode curr = head; //当前指针节点
//每次循环,都将当前节点指向它前面的节点,然后当前节点和前节点后移
while (curr != null) {
ListNode nextTemp = curr.next; //临时节点,暂存当前节点的下一节点,用于后移
curr.next = prev; //将当前节点指向它前面的节点
prev = curr; //前指针后移
curr = nextTemp; //当前指针后移
}
return prev;
// ListNode ans = null;
// for (ListNode x = head; x != null; x = x.next) {
// ans = new ListNode(x.val,ans);
// }
// return ans;
}
}
第二题,删除排序链表中的重复元素
分析:如果出现相等的,直接进行下一个
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if (head == null) {
return head;
}
ListNode cur = head;
while (cur.next != null) {
if (cur.val == cur.next.val) {
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
return head;
}
}
第十天
第一题,有效的括号
, 分析:这道题的解法可以
代码段
class Solution {
public boolean isValid(String s) {
int n = s.length();
if (n % 2 == 1) {
return false;
}
Map<Character, Character> pairs = new HashMap<Character, Character>() {{
put(')', '(');
put(']', '[');
put('}', '{');
}};
Deque<Character> stack = new LinkedList<Character>();
for (int i = 0; i < n; i++) {
char ch = s.charAt(i);
if (pairs.containsKey(ch)) {
if (stack.isEmpty() || stack.peek() != pairs.get(ch)) {
return false;
}
stack.pop();
} else {
stack.push(ch);
}
}
return stack.isEmpty();
}
}
第二题,用栈实现队列
说实话,这道题我是真的不怎么会,我想了一会儿,写出来一个编译错误。
这里是答案
class MyQueue {
Deque<Integer> inStack;
Deque<Integer> outStack;
public MyQueue() {
inStack = new LinkedList<Integer>();
outStack = new LinkedList<Integer>();
}
public void push(int x) {
inStack.push(x);
}
public int pop() {
if (outStack.isEmpty()) {
in2out();
}
return outStack.pop();
}
public int peek() {
if (outStack.isEmpty()) {
in2out();
}
return outStack.peek();
}
public boolean empty() {
return inStack.isEmpty() && outStack.isEmpty();
}
private void in2out() {
while (!inStack.isEmpty()) {
outStack.push(inStack.pop());
}
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();//返回队列开头的元素
* boolean param_4 = obj.empty();//如果队列为空返回true
*/
第十一天
第一题,二叉树的前序遍历
分析:这个太简单了,不用分析了
/**
* 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<Integer> preorderTraversal(TreeNode root) {
ArrayList<Integer> res = new ArrayList<>();
if (root ==null) return res;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode curr = stack.pop();
res.add(curr.val);
if (curr.right != null) stack.push(curr.right);
if (curr.left != null) stack.push(curr.left);
}
return res;
}
}
第二题,中序遍历
/**
* 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<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<>();
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
res.add(root.val);
root = root.right;
}
return res;
}
}
第三天 ,后序遍历
/**
* 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<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<>();TreeNode prev = null;
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
if (root.right == null || root.right == prev) {
res.add(root.val);
prev = root;
root = null;
} else {
stack.push(root);
root = root.right;
}
}
return res;
}
}
第十二天
第一题,二叉数的层序遍历
分析:
输出结果是一个嵌套的数组集合,说明要定义两个数组。
分析临界值,如果出现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 List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> lists = new ArrayList<>();
if (root == null) {
return lists;
}
List<TreeNode> node = new ArrayList<>();
node.add(root);
while (!node.isEmpty()) {
int size = node.size();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode remove = node.remove(0);
list.add(remove.val);
if (remove.left != null) {
node.add(remove.left);
}
if (remove.right != null) {
node.add(remove.right);
}
}
lists.add(list);
}
return lists;
}
}
第二题,二叉树的最大深度
/**
* 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 int maxDepth(TreeNode root) {
if (root == null) {
return 0;
} else {
int leftHeight = maxDepth(root.left);
int rightHeight = maxDepth(root.right);
return Math.max(leftHeight, rightHeight) + 1;
}
}
}
第三题,对称二叉树
分析:最开始我没有想到用递归的思路,直到后来,才发现递归的方式要更简单,更好。
/**
* 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 {
/**
*首先注意节点的范围是在【1,100】之间,说明不需要考虑空值的情况
*/
public boolean isSymmetric(TreeNode root) {
TreeNode node1=root.left;
TreeNode node2=root.right;
return check(node1,node2);
}
public boolean check(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
}
if (p == null || q == null) {
return false;
}
return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);
}
}
第十三天:
第一题,翻转二叉树
/**
* 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 TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
TreeNode left = invertTree(root.left);
TreeNode right = invertTree(root.right);
root.left = right;
root.right = left;
return root;
}
}
第二题:路径总和
分析:存在某一条路径之后等于目标值,就返回true,如果全部执行完成之后还没有得到true,会返回false。
/**
* 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 {
/**
分析,首先需要知道,题目给我们的意思
targetSum=一条路径里面的所有节点值的和
*/
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) {
return false;
}
if (root.left == null && root.right == null) {
return targetSum == root.val;
}
return hasPathSum(root.left, targetSum- root.val) || hasPathSum(root.right, targetSum - root.val);
}
}
第三题,二叉树的搜索数中的搜索
/**
* 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 TreeNode searchBST(TreeNode root, int val) {
while (root != null) {
if (val == root.val) {
return root;
}
root = val < root.val ? root.left : root.right;
}
return 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 TreeNode searchBST(TreeNode root, int val) {
while (root != null) {
if (val == root.val) {
return root;
}
root = val < root.val ? root.left : root.right;
}
return null;
}
}
第二题,验证二叉搜索数,
分析:如果该二叉树中的一个节点中出现了一个root.left.val的值大于root.val的值,此时会返回false,如果没有出现这一情况,则会返回true,
代码段
/**
* 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 {
private TreeNode pre = null;
public boolean isValidBST(TreeNode root) {
return isValid(root);
}
private boolean isValid(TreeNode root){
if(root == null) return true; // 空节点,返回默认为true
boolean left = isValid(root.left);
if(pre!=null && pre.val>=root.val) return false; // 逆序,返回false
pre = root; // 保存上一个节点
boolean right = isValid(root.right);
return left && right;
}
}
第三题,两数之和,输入BST
分析:这道题可以采用HashSet的方法来进行这道题的解答
/**
* 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 findTarget(TreeNode root, int k) {
Set < Integer > set = new HashSet();
return find(root, k, set);
}
public boolean find(TreeNode root, int k, Set < Integer > set) {
if (root == null)
return false;
if (set.contains(k - root.val))
return true;
set.add(root.val);
return find(root.left, k, set) || find(root.right, k, set);
}
}
第四题,二叉数的最近的公共祖先
分析:看了一遍题目,去写,老是出现报错,最后执行总是出现那个错误,我去看了一下答案,答案它是先进行的递归,直到最后的值
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root== null || root == p || root == q)
return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left == null)
return right;
//同上
if (right == null)
return left;
return root;
}
}