力扣第223场周赛

1. 解码异或后的数组

简单题,题解:a ^ b ^ b= 0,用结果和原数组在异或一下就可以了。

class Solution {
public:
    vector<int> decode(vector<int>& encoded, int first) {
        vector <int >ans;
        ans.push_back(first);
        int n = encoded.size();
        for(int i=0;i<n;i++)
            ans.push_back(encoded[i]^ans[i]);
        return ans;
    }
    
};

2.交换链表中的节点

简单题。首先计算链表长度,然后找到要交换的两个点的值,再找到要交换的两个点,修改他们的val值即可。

class Solution {
public:
    int fun(int k,ListNode* head){
        while(k!=1){
            k--;
            head=head->next;
        }
        return head->val;
    }
    ListNode* swapNodes(ListNode* head, int k) {
        auto p=head;
        int n=0;
        while(p!=NULL) {
            p=p->next;
            n++;
        }
        p = head;
        int kk = n-k+1;
        int num=1; 
        int c1 = fun(k,head);
        int c2 = fun(kk,head); 
        bool flag1=0,flag2=0;
        while(p!=NULL){
            if(num==k) {
                p->val=c2;
                flag1=1;
                if(flag2) break;
            }
            if(num==kk){
                p->val = c1;
                flag2=1;
                if(flag1) break;            
            }
            p = p->next;
            num++;
        }
        return head;
    }
};

3.执行交换操作的最小汉明距离

中档题。思路: 如果0和1,1和2可以交换,那么0 1 2 这三个位置的数可以是一个全排列。所以我们根据可以构建一个无向图,若a和b可以交换,那么a b之间就有一条边。图的每个联通分量都可以进行全排列。对每个联通分量判断有多少个不相等的元素然后累加一下就可以了(也可求相等的最后在减一下)

class Solution {
public:
    bool flag[100000+7];
    vector<int>ve[100000+7];
    vector<int>v;
    map<int ,int >mp;
    void dfs(int pos){
        if(flag[pos]) return ;
        v.push_back(pos);
        flag[pos]=1;
        for(int i=0;i<ve[pos].size();i++){
            dfs(ve[pos][i]);
        }
    }
    int minimumHammingDistance(vector<int>& source, vector<int>& target, vector<vector<int>>& allowedSwaps) {
        int n =allowedSwaps.size();
        for(int i=0;i<n;i++){
            ve[allowedSwaps[i][1]].push_back(allowedSwaps[i][0]);
            ve[allowedSwaps[i][0]].push_back(allowedSwaps[i][1]);
        }
        int ans=0;
        mp.clear();
        v.clear();
        n = source.size();
        for(int i=0;i<n;i++){
            dfs(i);
            int c=v.size();
            
            for(int i=0;i<c;i++) mp[source[v[i]]]++;
            
            
            for(int i=0;i<c;i++){
                if(mp[target[v[i]]]){
                    ans++;
                    mp[target[v[i]]]--;
                }
            } 
            v.clear();
            mp.clear();
        }
        return n-ans;
        
    }
};

4.完成所有工作的最短时间

困难题。思路:状压dp。jobs的长度为n,我们可以用[0,2^n-1]中的任何一个数来代表jobs的一个子集i。设j是子集i里的一个元素。val[i]代表子集i的总的工作时间。

val[i] = val[i-j]+val[j]

定义状态dp[i][j]表示工作子集为j时,前i个人里边花费的时间最小值。
状态转移方程

int ci = max(dp[i-1][j-s] ,val[s])
dp[i][j] =min(ci)

其中s表示的集合j的子集。
code:

class Solution {
public:
    int val[(1<<12)+7];
    int dp[13][(1<<12)+7];
    int INF=1e9+7;
    int minimumTimeRequired(vector<int>& jobs, int k) {
    	int n=jobs.size();
        memset(dp,0,sizeof dp);
        memset(val,0,sizeof val);
        for(int i=0;i<(1<<n);i++){
		    int p=i;
		    int pos=0;
		    while(p){
			    val[i]+= (p&1)? jobs[pos]:0; 
			    p>>=1;
			    pos++; 
		    }
        }
        for(int i=0;i<(1<<n);i++) dp[1][i] = val[i];
	    for(int j=2;j<=k;j++){
		    for(int i=0;i<(1<<n);i++){	
			    int minv = INF;
			    for(int s=i;s;s=(s-1)&i){
			    	minv = min(minv,max(dp[j-1][i-s],val[s])); 	
			    }
			    dp[j][i] = minv;
		    }
	    }
        return dp[k][(1<<n)-1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值