学习内容:

LeeCodeJava

LeeCode

674.最长连续递增序列(简单)

代码:

  1. class Solution {
  2. public int findLengthOfLCIS(int[] nums) {
  3. if(nums.length==0){
  4. return 0;
  5. }
  6. int max=-1;
  7. int length=0;
  8. for (int i = 0; i < nums.length; i++) {
  9. if(i==0||nums[i]>nums[i-1]){
  10. length++;
  11. if(i==nums.length-1&&length>max){
  12. max=length;
  13. }
  14. }else if(nums[i]<=nums[i-1]){
  15. if (max <= length) {
  16. max = length;
  17. }
  18. length=1;
  19. }
  20. }
  21. return max;
  22. }
  23. }

思路:

先利用一个对于长度的判断来防止空集合对于结果的影响,随后设定一个last值作为上一个元素的数值记录,如果这次的等于上次的,那么就将这次的计入.,否则进行判定,如果这个序列的值大于最大的,那么将其的长度作为最大的长度,随后将长度记录置零,重新技术.

注意点

1.要注意数组不能越界,所以要特别对于第一个进行检测.
2.要注意存在最后一个节点是顺延下去的情况,所以需要额外检测,如果是最后一个的话,需要强制导出一次length与max进行比较.

优解代码:

  1. class Solution {
  2. public int findLengthOfLCIS(int[] nums) {
  3. int result = 0;
  4. int l = 0;
  5. int r = 0;
  6. int count = 0;
  7. for (int i = 0; i < nums.length; i++) {
  8. count = 1;
  9. l = i;
  10. r = i + 1;
  11. while ((r < nums.length) && (nums[l] < nums[r])) {
  12. l++;
  13. r++;
  14. count++;
  15. }
  16. i = r - 1;
  17. if (result < count) {
  18. result = count;
  19. }
  20. }
  21. return result;
  22. }
  23. }

思路:

使用两个指针来保证逻辑的完整性,一个前,一个后,都可以使用++来处理,每个起始值都对应一个while来负责找到目标位置,减可以通过给while来添加限定条件来使得代码的逻辑更加完整,总而言之,虽然使用的内存只少了一点,但是比我的代码优雅很多.

130.二叉树展开为链表(中等)

我的代码

  1. class Solution {
  2. public void flatten(TreeNode root) {
  3. ArrayList<TreeNode> treeNodeArrayList=new ArrayList<>();
  4. if(root==null){
  5. return;
  6. }
  7. preOrder(treeNodeArrayList,root);
  8. root.left=null;
  9. TreeNode cur=root;
  10. for (int i = 1; i < treeNodeArrayList.size(); i++) {
  11. cur.right=treeNodeArrayList.get(i);
  12. cur=cur.right;
  13. }
  14. }
  15. private void preOrder(ArrayList<TreeNode> arrayList,TreeNode cur){
  16. if(cur==null){
  17. return;
  18. }
  19. arrayList.add(new TreeNode(cur.val,null,null));
  20. preOrder(arrayList,cur.left);
  21. preOrder(arrayList,cur.right);
  22. }
  23. }

初步思路:

无思路,据说可以使用原地算法,目前的想法,只有重新进行前序遍历,然后将Teenode的值输出.大致思路就是用cur来操作root节点,让root可以按照treearrayList的顺序,输出节点
注意,这种原地算法的要求是root不能改变原先的地址,不然会直接导致函数内的数据丢失.
改进方向:使用原先的节点,而不使用new.

改进代码

  1. class Solution {
  2. public void flatten(TreeNode root) {
  3. if(root==null){
  4. return;
  5. }
  6. ArrayList<TreeNode> treeNodeArrayList=new ArrayList<>();
  7. preOrder(treeNodeArrayList,root);
  8. root.left=null;
  9. TreeNode cur=root;
  10. for (int i = 1; i < treeNodeArrayList.size(); i++) {
  11. cur.right=treeNodeArrayList.get(i);
  12. cur.right.left=null;
  13. cur=cur.right;
  14. }
  15. }
  16. private void preOrder(ArrayList<TreeNode> arrayList,TreeNode cur){
  17. if(cur==null){
  18. return;
  19. }
  20. arrayList.add(cur);
  21. preOrder(arrayList,cur.left);
  22. preOrder(arrayList,cur.right);
  23. }
  24. }

结果发现需要的内存不降反增,改进失败.

优解代码

  1. class Solution {
  2. public void flatten(TreeNode root) {
  3. if (root == null) {
  4. return;
  5. }
  6. flatten(root.left);
  7. flatten(root.right);
  8. TreeNode left = root.left;
  9. TreeNode right = root.right;
  10. root.left = null;
  11. //左侧空置
  12. root.right = left;
  13. //右侧的值变成左值
  14. TreeNode p = root;
  15. //用p缓存root
  16. while(p.right != null) {
  17. p = p.right;
  18. //根节点向右下移动
  19. }
  20. p.right = right;
  21. //使左节点的下一个变成右节点
  22. }
  23. }

思路:

实质上是一个在先序遍历的过程中整理节点的过程,从底部开始整理;
1.左孩子移到右孩子的位置.
2.如果右孩子不是null的话,将光标向右孩子处移动,然后将原先的右孩子移动到现在右孩子(之前的左孩子)的右孩子处.
3.因为是从底部开始的,所以每个孩子实际上已经被规整成了一个一个的
4.使用while的原因是因为此时的左孩子不一定是一个,而可能是一串,所以需要找到现有左孩子最小的那个节点.
5,很优雅,很有效