【算法】Dya05

努力经营当下,直至未来明朗!


普通小孩也要热爱生活!

1. 删除链表中重复的节点

删除链表中重复的节点
1)思路:

① 如果要删除重复的节点,一定要知道第一个重复节点前的节点p以及重复的最后一个结点q。(即前开后闭
② 找到之后:p.next = q.next 即可。
写一个头节点比较好,如果第一个结点就是重复节点,那头结点其实就可以保证前开后闭。
④ 注意找重复节点的细节!
⑤ 注意循环的条件
⑥ 注意返回值!

2)代码:

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public ListNode deleteDuplication(ListNode pHead) {
        if(pHead == null) {
            return pHead;
        }

        // 首先设定一个头结点
        ListNode head = new ListNode(0);
        head.next = pHead;

        // 这里的话就说明是可以开始寻找重复的区间了
        ListNode prev = head;
        ListNode last= head.next;
        

        while(last != null) {
            while(last.next!=null && last.val!=last.next.val) {
                // 此时说明并没有重复,prev和last整体后移
                prev = last;
                last = last.next;
            }

            while(last.next!=null && last.val==last.next.val) {
                // 此时说明有重复,last后移直到找到最后一个重复的位置
                last = last.next;
             }

            // 来到这里,说明:
            // 1. last.next!=null,此时确定一段重复范围(prev,last]
            // 2. last.next==null,此时也确定一段范围(prev,last]
            // 3. last.next==null,但是没有一段范围
            
            // 判断有没有确定一段范围
            if(prev.next != last) {
                prev.next = last.next;
            }
            last = last.next;

        }
        
        pHead = head.next;
        return pHead;

    }
}


2. 包含min函数的栈

包含min函数的栈
1)面试官很容易问:如果弹出第二小、第三小呢?
2)思路:

① 栈:先进后出
② 使用辅助栈结构:辅助栈中只放最小的元素!
③ 所以:辅助栈中的栈顶元素就是最小元素,其次就是第二、第三…可以进行弹栈操作
④ 辅助栈特性:元素个数永远与数据栈中的个数相同;辅助栈栈顶永远保存当前数据栈的最小值;其中,辅助栈中数据可能存在大量重复值。

3)代码:

import java.util.Stack;

public class Solution {
    //定义数据栈和辅助栈
    Stack<Integer> data_stack = new Stack<>(); // 数据栈
    Stack<Integer> min_stack = new Stack<>(); // 辅助栈
    
    // 弹入
    public void push(int node) {
        // 进行判断后弹入
        if(min_stack.isEmpty() || (min_stack.peek()>node)) {
            min_stack.push(node);
        } else {
            min_stack.push(min_stack.peek());
        }
        // 无论如何数据都要存入数据栈
        data_stack.push(node);
    }
    
    // 弹出
    public void pop() {
        data_stack.pop();
        min_stack.pop();
    }
    
    // 栈顶元素:数据栈栈顶元素
    public int top() {
        return data_stack.peek();
    }
    
    // 最小元素:辅助栈栈顶元素就是min
    public int min() {
        return min_stack.peek();
    }
}


3. 栈的压入、弹出序列

栈的压入、弹出序列
1)思路:

① 弹出序列的第一个元素必定是最后入栈的
② 如果遇到入栈元素与出栈的元素相等,此时开始进行弹出序列,否则持续入栈直至相等;直到发现弹出序列与栈中的元素不相等,此时就继续入栈,重复以上判断操作
③ 直到最后已经压入所有元素,如果此时栈为空就说明是,否则不是!
④ 主要是使用循环实现的。

2)代码:

import java.util.ArrayList;
import java.util.Stack;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
      // 首先进行判断
      if(pushA==null || popA==null || pushA.length!=popA.length) {
        return false;
      }

      // 遍历pushA,并与popA比较【进行出入栈】
      Stack<Integer> stack = new Stack<>();
      int i = 0;
      int j = 0;
      for(; i<pushA.length; i++) {
        // 首先进行入栈操作,是一定有的
        stack.push(pushA[i]);
        // 入栈之后进行判断,栈顶元素是否与popA的首元素相等
        // popA首元素是会变化的
        // 注意使用循环
        while(!stack.isEmpty() && stack.peek()==popA[j]) {
            // 如果相等,就进行弹出操作,并且j++
            stack.pop();
            j++;
        }
      }

      return stack.isEmpty();
    }
}

4. 从上往下打印二叉树[层序遍历]

从上往下打印二叉树
1)思路:
使用队列

① 根结点入队列
② 出一个节点 (保存该节点,以便后续访问左右子结点)
③ 访问该节点,并将其左右子节点入队列(一定要注意判空
④ 然后重复②③步骤就行!(队列为空则访问结束)

2)代码:

import java.util.ArrayList;
import java.util.*;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        // 根据返回类型创建一个返回层序遍历结果的链表(存储值)
        ArrayList<Integer> ret = new ArrayList<>();

        // 首先进行判断
        if(root == null) {
            return ret;
        }

        // 存储的辅助队列(存储节点)
        Queue<TreeNode> queue = new LinkedList<>();
        // 将root入队列!
        queue.offer(root);

        // 首先进行遍历:入队列出队列
        // 注意保存出队列的值,后续进行访问及其左右子结点时需要
        while(!queue.isEmpty()) {
            // 出一个节点(注意保存该结点的值)
            TreeNode cur = queue.poll();
            // 并将弹出的节点保存到结果队列中
            ret.add(cur.val);

            // 然后将其左右节点压入队列
            // 但是注意判空操作
            if(cur.left != null) {
                queue.offer(cur.left);
            }
            if(cur.right != null) {
                queue.offer(cur.right);
            }
        }

        // 此时返回结果链表
        return ret;

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'Dream是普通小孩耶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值