【每日算法】数组 链表| day2 LC 160 88 206

160.相交链表

逻辑:

1.空判断:任意一个链表为空,则返回null

2.两个指针去遍历:都会相遇:

        相交:则在第一个相交节点

        不相交:公倍数的地方,最后的空指针

3.循环:两个指针不相等时

        分别,两个指针判断,到末尾则跳到另一个链表的头部

88.合并两个有序数组

 定义,三个指针

i,j 分别指向两个数组有意义的末尾,cur 指向合并数组长度的末尾

比较i,j 的大小,谁大放在cur指针的位置,并往前移

while 是防止 j 的越界

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i = m - 1;
        int j = n -1;
        int cur = nums1.length - 1;

        while(j >= 0){

            if( i >= 0 && nums1[i] > nums2[j]){
                nums1[cur] = nums1[i];
                i--;
                cur--;
            } else {
                nums1[cur] = nums2[j];
                j--;
                cur--;
            }
        }
    }
}

206.反转链表

原地逆置

递归思想 --- 5行代码

1.判空:返回传进来的head

2.递归:获取最后的头指针

3.让最后非空指针的下一个指向自己

4.让自己的下一个为空

5.返回头指针

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }

        ListNode cur = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return cur;
    }
}

25.K 个一组翻转链表 --- 自己的思路还不清晰

 

 代码思路:

1.构造新头节点,其下一个指向head

2.pre,end指针指向新头节点,end到时候遍历k个位置,标注未翻转的链表的前一个,相当于未翻转的链表的新头节点

3.遍历每k组,即end指针不为空

        3.1 将end遍历到k位置,即要反转的末尾

        3.2 如果发现 end == null,说明此时翻转的链表的节点数小于 k ,保存原有顺序就行

                直接跳出循环

        3.3 next指针指向end的下一个,是未翻转的head

                next 指针,是反转时要断掉连接,反转断链用的

        3.4 end 指针的下一个置空

        3.5 新头节点的下一个为 start 指针

        3.6 pre的下一个要断开

        3.7 反转链表 传进去start指针 返回pre.next

        3.8 【翻转链表区域】里面的尾节点的 next 指针指向【待翻转链表区域】里面的第一个节点

        3.9 pre = start;

        3.10 end = start;

4.返回新头节点的下一个

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(-1);

        dummy.next = head;

        ListNode pre = dummy;
        ListNode end = dummy;
        
        while( end.next != null){

            for(int i = 0 ; i < k && end != null ; i++){
                end = end.next ;
            }

            if(end == null){
                break;
            }

            ListNode next = end.next;
            end.next = null ;
            
            ListNode start = pre.next;
            pre.next = null;

            pre.next = reverse(start);

            start.next = next ;

            pre = start;
            end = start;
        }
        return dummy.next;

    }

    ListNode reverse(ListNode head){
        if(head == null || head.next == null) return head;

        ListNode cur = reverse(head.next);
        head.next.next = head;
        head.next = null;
        return cur;
    }
}

141.环形链表 --- 快慢指针的应用

两个判空操作:

        head == null || head.next == null ---- false

        fast == null || fast.next == null ---- false

public class Solution {
    public boolean hasCycle(ListNode head) {
       if(head == null || head.next == null) return false;
       ListNode p = head , q = head.next;

       while(p != q){
           if(q == null || q.next == null) return false;
           p = p.next;
           q = q.next.next;
       }

       return true;
    }
}

142.环形链表 II

就是在相遇的位置,重新开始遍历

定义两个指针,一个头,一个相遇位置,逐个往下遍历

由于,数学的相等,一定会在环形的开始节点 相遇

如果都没相遇,则返回空

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode p = head, q = head;
        while(q != null && q.next != null){
            p = p.next;
            q = q.next.next;
            
            if(p == q){
                ListNode b = q;
                ListNode a = head;
                while( a != b){
                    a = a.next;
                    b = b.next;
                }
                return a;
            }
        }
        return null;
    }
}

21.合并两个有序链表

代码逻辑:

构造新头节点,和遍历指针pre

l1,l2分别是传进来的两个链表的头节点

循环一直到某个链表为空

        比较l1,l2指针的大小,小于等于的让pre指向它,l1(小的一方)往后遍历进行比较

哪个链表不为空,则接到pre后面

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode dummy = new ListNode(-1);
        ListNode pre = dummy;

        while(list1 != null && list2 != null){
            if(list1.val <= list2.val){
                pre.next = list1;
                list1 = list1.next;
            } else {
                pre.next = list2;
                list2 = list2.next;
            }
            pre = pre.next;
        }

        if(list1 != null){
            pre.next = list1;
        }

        if(list2 != null){
            pre.next = list2;
        }

        return dummy.next;
    }
}

66.加一

代码逻辑:

从后往前, 遍历数组

如果是9 ,则该位置0,继续for循环

如果不是9,则该位置+1,并直接返回数据

在循环中如果每一位都是9,则没有返回,要进行数组的扩容操作

扩容操作 

1.new 新数组 大小为原数组的位数+1

2.第一位置1,其他位,默认为0

3.返回新数组

class Solution {
    public int[] plusOne(int[] digits) {
        for(int i = digits.length -1 ;i >= 0 ;i--){
            if(digits[i] == 9){
                digits[i] = 0;
            } else {
                digits[i] = digits[i] + 1;
                return digits;
            }
        }

        int[] res = new int[digits.length + 1];
        res[0] = 1;
        return res;
    }
}

栈和队列 --- 一般都是匹配问题

20.有效的括号

代码逻辑:

如果,其长度为奇数,则必定有一个不匹配

构造一个字符栈,存左括号

把字符串转换为数组的形式,方便获取字符串中的每个字符

string.toCharArray(); 方法要记住 

遍历字符串数组

        如果是左边的压入栈中

        否则,进行判断

                如果,栈为空,不匹配

                如果,不对应。。。。。对应,则栈要弹出

最后,返回栈是否为空

class Solution {
    public boolean isValid(String s) {
        if(s.length() % 2 == 1) return false;
        Stack<Character> stack = new  Stack<Character>();
        char charlist[] = s.toCharArray();

        for(int i = 0 ; i < charlist.length ; i++){
            if(charlist[i] == '(' || charlist[i] == '[' ||charlist[i] == '{'){
                stack.push(charlist[i]);
            } else {
                if(stack.isEmpty()) return false;

                char re = stack.peek();
                if(re == '(' && charlist[i] == ')' ||
                    re == '[' && charlist[i] == ']' ||
                    re == '{' && charlist[i] == '}'){
                        stack.pop();
                    } else {
                        return false;
                    }
            }
        }

        return stack.isEmpty();
    }
}

155.最小栈  --- 写了好几遍记住了

class MinStack {

    Stack<Integer> stack = null;
    Stack<Integer> min = null;

    public MinStack() {
        stack = new Stack<Integer>();
        min = new Stack<Integer>();
    }
    
    public void push(int val) {
        stack.push(val);
        if(min.isEmpty() || min.peek() > val){
            min.push(val);
        } else {
            min.push(min.peek());
        }
    }
    
    public void pop() {
        stack.pop();
        min.pop();
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int getMin() {
        return min.peek();
    }
}

150.逆波兰表达式求值 --- 后缀表达式求值

代码逻辑 : 栈的匹配问题

注意:数字弹出后 要 区分 前后顺序 除法是需要先后顺序的

数字栈,遇到符合,弹出两个对应 操作即可

class Solution {
    public int evalRPN(String[] tokens) {
        int left = 0 , right = 0 ,tmp = 0;
        Stack<Integer> stack = new Stack<Integer>();
        for(String token : tokens){
            if(!"+".equals(token) &&
                !"-".equals(token) &&
                !"*".equals(token) &&
                !"/".equals(token)){
                    stack.push(Integer.valueOf(token));
                } else {
                    right = Integer.valueOf(stack.pop());
                    left = Integer.valueOf(stack.pop());
                    if("+".equals(token)){
                        tmp = left + right;
                        stack.push(tmp);
                        tmp = 0;
                    } else if("-".equals(token)){
                        tmp = left - right;
                        stack.push(tmp);
                        tmp = 0;
                    } else if("*".equals(token)){
                        tmp = left * right;
                        stack.push(tmp);
                        tmp = 0;
                    } else if("/".equals(token)){
                        tmp = left / right;
                        stack.push(tmp);
                        tmp = 0;
                    }
                }
        }

        return stack.pop();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值