[每日两题系列]刷算法题咯~~

        本系列所选题目均来自力扣或者牛客网站. 所选题目主要是以其中的简单题为主, 中等题为辅, 包含少数困难题(原因是: 本人目前能力还不够~ ). 开展这个系列的目的是督促自己, 在暑假的时间里也要保持有一定的刷题量, 拒绝摆烂~
        话不多说, 直接开刷~~

用户分组

        题目描述: 有 n 个人被分成数量未知的组。每个人都被标记为一个从 0 到 n - 1 的唯一ID 。
        给定一个整数数组 groupSizes ,其中 groupSizes[i] 是第 i 个人所在的组的大小。例如,如果 groupSizes[1] = 3 ,则第 1 个人必须位于大小为 3 的组中。
        返回一个组列表,使每个人 i 都在一个大小为 groupSizes[i] 的组中。
        每个人应该 恰好只 出现在 一个组 中,并且每个人必须在一个组中。如果有多个答案,返回其中 任何 一个。可以 保证 给定输入 至少有一个 有效的解。

解题思路:
        (1) 这道题使用哈希桶的思想就可以简单解决.
        (2) 遍历数组, 将数组中的每一个元素添加到哈希表中对应 key 值的链表后面. 这里需要注意, 如若 key 值中没有链表存在(也就是第一次遍历到这个元素的时候), 那么需要先定义一个链表.
        (3) 由于在一个链表下面, 可能会有超过 key 值大小的节点存在, 那么这时候我们的解决方法是: 在每次往链表中添加节点之后, 判断当前链表的大小是否与对应的 key 值相等, 如若相等, 则可以先将这整个链表上所有节点都存到顺序表中, 然后将链表清空即可. 直到把数组遍历完, 返回顺序表即可.

实现代码:

class Solution {
    public List<List<Integer>> groupThePeople(int[] groupSizes) {
        Map<Integer, List<Integer>> map = new HashMap<>();
        List<List<Integer>> ret = new ArrayList<>();
        int len = groupSizes.length;
        for(int i = 0; i < len; i++){
            int x = groupSizes[i];
            if(map.get(x) == null){
                map.put(x, new ArrayList<>());
            }
            map.get(x).add(i);
            if(map.get(x).size() == x){
                ret.add(map.get(x));
                map.put(x, null);
            }
        }
        return ret;
    }
}

K个一组翻转链表

        题目描述: 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
        k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
        你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

解题思路:
        (1) 这道题我使用的是比较容易实现(不容易出错)的做法 — 使用栈来实现, 但是这种做法的时间复杂度和空间复杂度是会比较大的.
        (2) 每次将原链表的前 k 个节点添加到栈中, 然后再取出这些节点拼接到一个新的链表后面, 这样就可以实现 k 个为一组来进行翻转. 直到原链表遍历到 null 的时候.
        (3) 直到最后剩下的节点可能会不够 k 个, 就不能进行翻转, 那么这时候, 每位只需要再定义一个栈来再次将这些节点翻转一遍即可(翻转两次就相当于没执行翻转).
        (4) 有一点需要注意: 我们不是在原链表遍历到 null 的时候, 就判断它一定是不进行翻转的, 因为还可能会有一种情况, 当链表遍历到 null 的时候, 刚好是构成一组的(也就是刚好是 k 个节点), 所以还有把这种情况排除在外.
        (5) 还有一点值得注意的是: 我们在编写下面这段代码的时候, 这里的 if 语句是不能够省略的.

while(!stack.empty()){
	cur.next = stack.pop();
    cur = cur.next;
    if(stack.empty()){
		cur.next = null;
    }
}

        原因是: 如果去掉, 就可能会有一些测试用例是不通过的, 会因为返回的链表是一个(死)循环而报错(可以自己调试看看最终效果), 所以我们每次都需要手动地将最后一个节点的 next 值设为 null, 如此一来, 就万无一失了.

实现代码:

class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode Head = new ListNode();
        ListNode cur = Head;
        Stack<ListNode> stack = new Stack<>();
        Stack<ListNode> st = new Stack<>();
        while(head != null){
            int count = k;
            while(count > 0 && head != null){
                stack.push(head);
                head = head.next;
                count--;
            }
            if(head != null || (head == null && count == 0)){
                while(!stack.empty()){
                    cur.next = stack.pop();
                    cur = cur.next;
                    if(stack.empty()){
                        cur.next = null;
                    }
                }
            }else{
                while(!stack.empty()){
                    st.push(stack.pop());
                }
                while(!st.empty()){
                    cur.next = st.pop();
                    cur = cur.next;
                    if(stack.empty()){
                        cur.next = null;
                    }
                }
            }
        }
        return Head.next;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蔡欣致

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

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

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

打赏作者

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

抵扣说明:

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

余额充值