Leetcode每天五题-02

19.删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.

说明:
给定的 n 保证是有效的。

进阶:
你能尝试使用一趟扫描实现吗?
思路:

一个指针先走n-1步,然后两个指针一起走
走到要删除结点前面,删除即可

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode p = head;
        ListNode q = head;
        if(head == null || n < 1){
            return head;
        }
        //向前走n-1步
        while(--n > 0 && p.next != null){
            p = p.next;
        }
        //如果删除头结点
        if(p.next == null && n==0){
            return head.next;
        }
        //如果n过大
        else if(n > 0){
            return head;
        }
        //一般情况
        while(p.next.next!=null){
            p = p.next;
            q = q.next;
        }
        q.next = q.next.next;
        return head;
    }
}
  1. 有效的括号

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

示例:

输入: “()”
输出: true
输入: “()[]{}”
输出: true
输入: “(]”
输出: false
输入: “([)]”
输出: false
输入: “{[]}”
输出: true

备注:

参考CodeInterview上的解法,但是过不了([)]这样的情况

class Solution {
    public boolean isValid(String s) {
        if(s == null || s.equals("")){
            return true;
        }
        Stack<Character> stack = new Stack<>();
        char[] strArr = s.toCharArray();
        for(int i = 0;i < strArr.length; i++){
            //如果不是这三种有效字符
            if(strArr[i] !='[' && strArr[i] !=']'
              && strArr[i] !='{' && strArr[i] !='}'
              && strArr[i] !='(' && strArr[i] !=')'){
                return false;
            }
            
            if(stack.size() == 0){
                stack.push(strArr[i]);
            }else if(isMatch(stack.peek(),strArr[i])){
                stack.pop();
            }else{
                stack.push(strArr[i]);
            }
        }
        return stack.size() == 0;
    }
    public boolean isMatch(char c1,char c2){
        return (c1 == '(' && c2 == ')') 
            || (c1 == '[' && c2 == ']') 
            || (c1 == '{' && c2 == '}');
    }
}

讨论区看到的解法

class Solution:
    def isValid(self, s):
        while '{}' in s or '()' in s or '[]' in s:
            s = s.replace('{}', '')
            s = s.replace('[]', '')
            s = s.replace('()', '')
        return s == ''
  1. 合并两个有序链表

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

备注:

这种增加头结点的方法可以方便对链表的操作

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        //如果有一个为null
        if(l1 == null || l2 == null){
            return l1 == null ? l2 : l1;
        }
        ListNode head = new ListNode(-1);
        ListNode cur = head;
        while(l1!=null && l2 !=null){
            cur.next = l1.val <= l2.val ? l1 : l2;
            if(cur.next == l1){
            	l1 = l1.next;	
            }else{
            	l2 = l2.next;
            }
            cur = cur.next;
        }
        cur.next = l1 == null ? l2 : l1;
        return head.next;
    }
}
  1. 括号生成

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 n = 3,生成结果为:

[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

class Solution {
    public List<String> generateParenthesis(int n) {
		List<String> ans = new ArrayList<>();
		generateCore(ans, "", 0, 0, n);
		return ans;
	}

	private void generateCore(List<String> ans, String tmsAns, int left, int right, int len) {

		// 如果长度超过2*len 或者右括号比左括号多 则返回
		if (left + right > (len << 1) || right > left) {
			return;
		}
		// 左括号和右括号的长度相等且都达到了len
		if ((left ^ right) == 0 && (left ^ len) == 0)
			ans.add(tmsAns);

		// 右括号大于左括号时,不是合法的括号
		if (right <= left) {
			generateCore(ans, tmsAns + "(", left + 1, right, len);
			generateCore(ans, tmsAns + ")", left, right + 1, len);
		}

	}
}

23.合并K个有序链表

合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6

思路:

分治,两两归并

class Solution {
	public ListNode mergeKLists(ListNode[] lists) {

		if (lists.length == 0) {
			return null;
		} else if (lists.length == 1) {
			return lists[0];
		} else if (lists.length == 2) {
			return mergeTwoLists(lists[0], lists[1]);
		}
		int mid = lists.length >> 1;
		int high = lists.length;
		ListNode[] l1 = new ListNode[mid];
		for (int i = 0; i < mid; i++) {
			l1[i] = lists[i];
		}

		ListNode[] l2 = new ListNode[high - mid];
		for (int i = mid; i < high; i++) {
			l2[i - mid] = lists[i];
		}

		return mergeTwoLists(mergeKLists(l1), mergeKLists(l2));
	}

	public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
		// 如果有一个为null
		if (l1 == null || l2 == null) {
			return l1 == null ? l2 : l1;
		}
		ListNode head = new ListNode(-1);
		ListNode cur = head;
		while (l1 != null && l2 != null) {
			cur.next = l1.val <= l2.val ? l1 : l2;
			if (cur.next == l1) {
				l1 = l1.next;
			} else {
				l2 = l2.next;
			}
			cur = cur.next;
		}
		cur.next = l1 == null ? l2 : l1;
		return head.next;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值