【2021】阿里巴巴编程题(4星)

1、子集

在这里插入图片描述
思路:之前的最长上升子序列针对的是一个数,本题说的是一个整体Node(x和y)都有有序,求他们的最长上升子序列。固定一个求另一个。将x由小到大排序,x相同时y由大到小排序(故意放错以免将x相同情况也计算入内),y的最长上升子序列就是答案了。
因为dp方法求lis会超时,所以这题只能用二分查找了。

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        for (int k = 0; k < m; k++) {
            int n = sc.nextInt();
            int[][] matrix = new int[n][2];
            for (int i = 0; i < n; i++) {
                matrix[i][0] = sc.nextInt();
            }
            for (int i = 0; i < n; i++) {
                matrix[i][1] = sc.nextInt();
            }
            //sort
            Arrays.sort(matrix, (x, y) -> (x[0] != y[0] ? x[0] - y[0] : y[1] - x[1]));
            int res = fun(matrix);
            System.out.println(res);
        }
    }

    //二分查找求y的最长上升子序列
    public static int fun(int[][] matrix) {
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < matrix.length; i++) {
            int poker = matrix[i][1];
            int left = 0, right = list.size() - 1;
            while (left <= right) {
                int mid = left + (right - left) / 2;
                if (list.get(mid) < poker) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            if (left == list.size()) {
                list.add(poker);
            } else {
                list.set(left, poker);
            }
        }
        return list.size();
    }
}

9、合法连续子段

在这里插入图片描述在这里插入图片描述
滑动窗口,不满足条件右移,满足条件左移,左移时更新答案。



import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int k = sc.nextInt();
        int[] nums = new int[m];
        for (int i = 0; i < m; i++) {
            nums[i] = sc.nextInt();
        }

        HashMap<Integer, Integer> window = new HashMap<>();
        int left = 0, right = 0, start = 0, end = 0, valid = 0, res = 0;
        while (right < nums.length) {
            int x = nums[right];
            right++;
            int time = window.getOrDefault(x, 0);
            window.put(x, time + 1);
            if (time + 1 > valid) valid = time + 1;
            while (valid == k) {
                res += nums.length - right + 1;
                int y = nums[left];
                left++;
                int time2 = window.get(y);
                if (time2 == k) {
                    valid--;
                }
                window.put(y, time2 - 1);
            }
        }
        System.out.println(res);
    }
}

10、两个序列

思路:设置映射规则,求最长连续上升子序列长度,返回n-lis。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int m=sc.nextInt();
        int[] a=new int[m];
        int[] b=new int[m];
        HashMap<Integer, Integer> map=new HashMap<>();
        for(int j=0; j<m; j++){
            a[j]=sc.nextInt();
            map.put(a[j],j);
        }
        for(int j=0; j<m; j++){
            b[j]=sc.nextInt();
            b[j]=map.get(b[j]);
        }
        int len=fun(b);
        System.out.println(m-len);
    }
    
    public static int fun(int[] b){
        int res=1;
        int cnt=1;
        for(int i=1; i<b.length; i++){
            if(b[i-1]<b[i]) cnt++;
            else cnt=1;
            res=Math.max(res, cnt);
        }
        return res;
    }
}

16进制数中1的个数

在这里插入图片描述

package com.atguigu;

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        char[] chars = str.substring(2).toCharArray();
        int res = 0;
        int[] map = new int[]{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
        for (int i = 0; i < chars.length; i++) {
            if (Character.isLetter(chars[i])) res += map[chars[i] - 'a' + 10];
            else res += map[chars[i] - '0'];
        }
        System.out.println(res);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值