LeetCode周赛涂房子

1.重新排列数组

1.重新排列数组
很简单,把数组分别插入一个新数组就行,cpp的vector使用push_back方法更简单。

    public int[] shuffle(int[] nums, int n) {
        int[] res = new int[2*n];
        for(int i=0;i<2*n;i+=2){
            res[i]=nums[i/2];
            res[i+1]=nums[i/2+n];
        }
        return res;
    }

2.数组中的 k 个最强值

2.数组中的 k 个最强值
t2有两种思路,我这里使用的双指针,因为答案一定是从排序过后的数组两端出来的,所以用两个指针不断比较,填满答案即可。
第二种思路是基于cpp的sort方法中的重载方法,通过重写cmp方法来达到。

    public int[] getStrongest(int[] arr, int k) {
        Arrays.sort(arr);
        int m=0,n=arr.length;
        if(n%2==0){
            m=(arr[n/2-1]);
        }
        else m=arr[n/2];
        int[] res = new int[k];
        int left=0,right=arr.length-1,i=0;
        while(k>0){
            if(Math.abs(arr[left]-m)<Math.abs(arr[right]-m)) {
                res[i] = arr[right];
                right--;
            }
            else if(Math.abs(arr[left]-m)>Math.abs(arr[right]-m)) {
                res[i]=arr[left];
                left++;
            }
            else{
                if(arr[left]>arr[right]) {
                    res[i]=arr[left];
                    left++;
                }
                else{
                    res[i] = arr[right];
                    right--;
                }
            }
            i++;
            k--;
        }
        return res;
    }

基于cmp的写法会简洁很多

int M;
int Abs(int x){
    if (x < 0) return -x;
    return x;
}
bool cmp(int a, int b){
    if (Abs(a - M) != Abs(b - M)) return Abs(a - M) > Abs(b - M);
    return a > b;
}

class Solution {
public:
    vector<int> getStrongest(vector<int>& arr, int k) {
        int n = arr.size();
        sort(arr.begin(), arr.end());
        M = arr[(n - 1) / 2];
        sort(arr.begin(), arr.end(), cmp);
        
        vector<int> ans;
        for (int i = 0; i < k; i++) ans.push_back(arr[i]);
        
        return ans;
    }
};

3.设计浏览器历史记录

模拟题,可以用数组或者list去模拟,操作一个指针来确定当前所在的页的序号即可,细节较多,主要是防止越界和处理vistt函数,要求并不低。

class BrowserHistory {
    List<String> his;
    int cur;
    public BrowserHistory(String homepage) {
        his = new LinkedList<>();
        cur=1;
        visit(homepage);
    }

    public void visit(String url) {
        while(his.size()>cur){
            his.remove(his.size()-1);
        }
        his.add(url);
        cur=his.size();

    }

    public String back(int steps) {
        if(cur-steps<1) {
            cur=1;
            return his.get(0);
        }
        else  {
            int curStr = cur-steps-1;
            cur=cur-steps;
            return his.get(curStr);
        }
    }
    
    public String forward(int steps) {
        String res = new String();
        if(cur+steps>his.size()){
            res=his.get(his.size()-1);
            cur=his.size();
        }
        else {
            res = his.get(cur+steps-1);
            cur=cur+steps;
        }
        return res;
    }
}

4.给房子涂色 III(我还是不会,参考的大佬代码)

多维dp,分别包括了前面多少个房子用了哪些颜色形成了多少个街区。数据规模较小,和前两场的t4比较像,可以尽情写很多层for来跑dp。
这个题目的核心转移方程主要是两种情况,一种是和前面房子颜色一致时,街区数量不变,cost增加,一种是颜色不一致是,街区增加。

    public int minCost(int[] houses, int[][] cost, int m, int n, int target) {
        int BIG = 10000000;
        int ret = -1;
        int[][][] dp = new int[m][target][n];//前m个房子,多少个街区,最后一间房子的颜色的最小化费。
        for(int i=0;i<m;i++){
            for(int j=0;j<target;j++){
                for(int k=0;k<n;k++){
                    dp[i][j][k]=BIG;
                }
            }
        }
        //初始化,第一个房子,切一个街区,房子颜色为,需要的最小花费
        if(houses[0]==0) {
            for (int k = 0; k < n; k++) {
                dp[0][0][k] = (houses[0] == k + 1) ? 0 : cost[0][k];
            }
        }else{
            dp[0][0][houses[0]-1]=0;//已经上过色不花钱
        }
        for(int i=1;i<m;i++){
            for(int j=0;j<target;j++){
                for(int k=0;k<n;k++){
                    if(houses[i]!=0&&k+1!=houses[i]){
                        continue;//该房子上过色且颜色不同
                    }
                    int costMoney = (houses[i]==k+1)?0:cost[i][k];
                    int ans = Integer.MAX_VALUE;//第一维是房子数,第二维是街区数,第三维是颜色
                    for(int h=0;h<n;h++){//之前的所有颜色遍历
                        if(k==h){//颜色不同相同,街区数+1
                            ans=Math.min(ans,dp[i-1][j][h]+costMoney);
                        }else{
                            if(j>0) {//防越界,且颜色相同
                                ans = Math.min(ans, dp[i - 1][j - 1][h] + costMoney);
                            }
                        }
                    }
                    dp[i][j][k]=Math.min(dp[i][j][k],ans);
                }
            }
        }
        int ans = BIG;
        for(int i=0;i<n;i++){
            ans = Math.min(ans,dp[m-1][target-1][i]);
        }
        return ans==BIG?-1:ans;
    }

(我太菜了还想再ak一次周赛)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值