Leetcode刷题(k个一组翻转链表、字节跳动往年的真题)

k个一组翻转链表
题目一描述

给定一个链表,将链表中的k个元素进行翻转,最后不满足k个元素的整数倍的元素,不进行翻转。

例如:
输入:1->2->3->4->5
k=2时: 返回2->1->4->3->5
k=3时:返回3->2->1->4->5

题目传送

题目一分析

该题目是一道困难的题目,但是对于链表这种数据结构的题目一般都不是特别难。可以使用一个指针窗口进行翻转窗口内的所有节点,但是这样的做题需要多个指针,比较乱。
我使用额外的空间辅助翻转链表,将链表中的k个元素为一组,压入栈中,一次将其弹出挂载到一个新的链表中,需要注意的是小心链表成环问题。

代码如下
 //将将链表中的元素以k为单位进行反转
    public static ListNode reverseKGroup(ListNode head, int k) {
        ListNode root = new ListNode(-1);
        ListNode curnode = head;
        ListNode pre = root;
        pre.next = head;
        //使用一个栈结构进行反转。每次入栈k个元素,然后弹出元素
        Stack<ListNode> stack = new Stack<>();
        while(curnode!=null){
            int temp = k;
            ListNode tempNode = curnode;
            //入栈链表的k个元素
            while(tempNode!=null&&temp-->0){
                stack.push(tempNode);
                tempNode = tempNode.next;
            }
            //如果最后不满足的几个元素不入栈操作
            if(tempNode==null&&temp!=0){
                pre.next = curnode;
                break;
            }
            //反转链表,即将元素从栈中弹出
            curnode = tempNode;
            while(!stack.isEmpty()){
                pre.next = stack.pop();
                pre = pre.next;
            }
            //必须将其设置为nul否则会引起链表成环
            pre.next = null;
        }
        return root.next;
    }
用户喜好
题目二描述

题目描述的相当复杂,阅读题目我都开始怀疑自己的中文水平了。大致说明一下题目的意思:第一行表示n个用户,第二行表示5个用户对某个文章的喜好程度,第三行表示给出的查询条数q,需要查询的是后面的q行,每行表示l到r之间用户喜好为k的用户数量
例如:

5
1 2 3 3 5
3
1 2 1
2 4 5
3 5 3
输出是:
1
0
2

去完成真题测试

题目二分析

题目读完就差不多想要放弃了吧,不过为了大厂还是要多准备的,一开始想着将用户喜好放在一个容器中,然后根据每个查询条件去匹配原来的容器,将查询结果返回,当然是天真,时间复杂度太高。
更改策略:使用一个map将用户喜好以及对应的下标记录下来,相当于一个分组处理过程,遍历起来就快了很多。

代码如下

暴力搜索,当然不尽人意

 private static void userHouby() throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.valueOf(bf.readLine());
        //将用户喜好放在一个数组中,后面进行匹配
        String[] num = bf.readLine().split(" ");
        int q = Integer.valueOf(bf.readLine());
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<q;i++){
            String[] temp = bf.readLine().split(" ");
            int left = Integer.valueOf(temp[0]);
            int right = Integer.valueOf(temp[1]);
            int k = Integer.valueOf(temp[2]);
            int res= searchNum(num,left,right,k);
            sb.append(res+"\n");
        }
        System.out.println(sb.toString());
    }
	//用户喜好的数组,当前需要查询的范围left,right以及喜好是k
    public static int searchNum(String[] num,int left,int right,int k){
        int res = 0;
        for(int i=left-1;i<right;i++){
            int temp = Integer.valueOf(num[i]);
            if(temp == k)res++;
        }
        return res;
    }

优化算法

//使用map将用户的喜好记录下来
    private static void customerHoby() throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.valueOf(bf.readLine());
        Map<String, List<Integer>> map = new HashMap<>();
        String[] num = bf.readLine().split(" ");
        //记录用户的喜好以及对应的下标位置
        for(int i = 0;i<n;i++){
            List<Integer> list = null;
            if(map.containsKey(num[i])){
                list = map.get(num[i]);
            }else {
                list = new ArrayList<>();
            }
            list.add(i);
            map.put(num[i],list);
        }
        int q = Integer.valueOf(bf.readLine());
        StringBuilder sb = new StringBuilder();
        //处理q条查询语句
        for(int i=0;i<q;i++){
            String[] temp = bf.readLine().split(" ");
            if(map.containsKey(temp[2])){
                int res = searchList(map.get(temp[2]),Integer.valueOf(temp[0]),Integer.valueOf(temp[1]));
                sb.append(res+"\n");
            }else{
                sb.append(0+"\n");
            }
        }
        System.out.println(sb.toString());
    }
    //查看链表中有多少个元素位置满足要求
    public static int searchList(List<Integer> list,int left,int right){
        int sum = 0;
        for(int i=0;i<list.size();i++){
            if(list.get(i) <= right-1 && list.get(i) >= left-1){
                sum++;
            }else if(list.get(i)>right){
                break;
            }
        }
        return sum;
    }
手串问题
题目三描述

题目依旧复杂,想要阅读以下题目的可以去看看题目的描述。
输入第一行为n个串珠,每m个之间的颜色不能重复,一共有c中颜色
以下的n行为每个串珠的颜色分布。

例如:
5 2 3
3 1 2 3
0
2 2 3
1 2
1 3
输出是:
2
解释以下:有5个串珠,第一个串珠3中颜色,第二个串珠没有颜色,第三个串珠有两种颜色,第四个第五个有一种颜色
每两个之间不能够有重复的颜色,第三个珠子和第四个珠子都有2,第五个珠子和第一个珠子都有3,因此两个串珠不符合要求。

题目传送

题目三分析

有参考别人的讲解,做题的思路还是需要多加的练习的。对于颜色和串珠的信息是要使用容器存储起来的,题目多了一般就会知道将哪一个特征作为key,哪一个特征作为value存储起来。该题目是将颜色作为key,一个颜色对应的串珠组成一个链,如果链中的串珠小于要求的m说明不符合要求,最后将不符合要求的个数累加起来。

代码如下
public static void main(String[] args)throws IOException {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int c = sc.nextInt();
        //创建map存储颜色以及对应的串珠信息,并初始化链表
        Map<Integer,LinkedList<Integer>> map = new HashMap<>();
        for(int i=0;i<=c;i++){
            map.put(i,new LinkedList<>());
        }
		//将颜色与串珠信息添加到容器中
        for(int i=0;i<n;i++){
            int temp = sc.nextInt();
            for(int j=0;j<temp;j++){
                int color = sc.nextInt();
                LinkedList<Integer> list = map.get(color);
                list.add(i);
            }
        }
        //不符合要求的个数
        int error = 0;
        //一共有c种颜色,每种颜色进行判断,找出不符合要求的个数
        for(int i=1;i<=c;i++){
            LinkedList<Integer> tempList = map.get(i);
            for(int j=0;j<tempList.size();j++){
            //对于不是最后一个串珠,那么就计算相邻元素的信息
            //如果是最后一个元素的信息,就需要计算第一个串珠的信息,因为这是一个环状的手串
                if (j+1<tempList.size()&&tempList.get(j+1) - tempList.get(j)<m) {
                    error++;
                    break;
                }else if(j+1==tempList.size()&&tempList.get(0) - tempList.get(j)+n<m){
                    error++;
                    break;
                }
            }
        }
        System.out.println(error);
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值