首页 > 试题广场 >

珠玑妙算

[编程题]珠玑妙算
  • 热度指数:7154 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

现有一堆球颜色是红色(R)、黄色(Y)、绿色(G)或蓝色(B)各若干个,现在随机选四个球分别放入四个槽中,得到一个序列。例如,RGGB(槽1为红色,槽2、3为绿色,槽4为蓝色),需要你猜出这个颜色序列的组合。比如,你可能猜YRGB。要是猜对了某个槽的颜色,则算一次“猜中”。要是只是猜对了颜色但槽位猜错了,则算为一次“伪猜中”。要注意,“猜中”不能算入“伪猜中”。给定两个string Aguess。分别表示颜色序列的组合和一个猜测。需要返回一个int数组,数组第一个元素为猜中的次数,第二个元素为伪猜中的次数。

测试样例:
"RGBY","GGRR"
返回:[1,1]
//差点没看懂题目=_=
class Result {
public:
    vector<int> calcResult(string A, string guess) {
        // write code here
        vector<int>res;
        int hash[128]={0};
        for(int i=0;i<A.size();++i)
            hash[A[i]]++;
        int cnt=0;
        for(int i=0;i<A.size();++i)
            if(A[i]==guess[i]) cnt++;
        res.push_back(cnt);
        cnt=0;
        for(int i=0;i<guess.size();++i){
            if(hash[guess[i]]!=0){
                ++cnt;
                --hash[guess[i]];
            }
        }
        res.push_back(cnt-res.back());
        return res;
    }
};

发表于 2019-09-02 18:25:41 回复(0)
更多回答
推荐
从题目中可以获取隐含信息:
“猜中” 属于 “伪猜中”,但是反过来不成立。

所有需要先统计猜中,
然后再统计 伪猜中个数= 可能的伪猜中个数 - 猜中个数

因此代码就比较容易写出来
import java.util.*;

public class Result {
	public int[] calcResult(String A, String guess) {
		if (A == null || guess == null) {
			return new int[] { 0, 0 };
		}
		// right 表示猜中
		// unright 表示伪猜中
		int right=0,unright=0;
		// 保存A中的<字符,字符个数>
		HashMap<Character, Integer> map = new HashMap<>();
		
		for (int i = 0; i < A.length(); ++i){
			// 统计猜中
			if(A.charAt(i) == guess.charAt(i))
				++right;
			
			// 获取A中的<字符,字符个数>
			Integer val = map.get(A.charAt(i));
			if(val==null){
				val=1;
			}else{
				val++;
			}
			map.put(A.charAt(i), val);
		}
		
		// 统计伪猜中的个数(猜中也属于伪猜中)
		for(int i=0;i<guess.length();++i){
			Integer val = map.get(guess.charAt(i));
			if(val != null && val >0){
				unright++;
				val--;
				if(val<0)
					val=0;
				map.put(guess.charAt(i), val);
			}
		}
		// 从伪猜中当中,去除猜中个数
		unright -=right;
		if(unright<0)unright = 0;
		return new int[] { right, unright };
	}
}

编辑于 2015-08-10 15:27:33 回复(1)
class Result {
public:
    vector<int> calcResult(string A, string guess) {
        // write code here
        vector<int> res(2, 0);
		for (int i = 0; i < 4; ++i){
			if (A[i] == guess[i]){
				res[0]++;
				A[i] = '0';
				guess[i] = '0';
			}
		}
		for (int i = 0; i < 4; ++i){
			if (guess[i] == '0')
				continue;
			for (int j = 0; j < 4; ++j){
				if (guess[i] == A[j]){
					res[1]++;
					A[j] = '0';
					break;
				}
			}
		}
		return res;
	}
};

发表于 2017-05-03 21:52:59 回复(2)
class Result {
public:
	vector<int> calcResult(string A, string guess) {
		int len = A.size();
		string a_left, guess_left;// 去除命中之后的字符串
		int hit = 0; //命中次数
		int miss = 0; //伪命中次数
		for (int i = 0; i < len; ++i)
		{
			if (A[i] == guess[i])
			{
				hit++;// 计算命中的次数
			}
			else{
				a_left.push_back(A[i]);
				guess_left.push_back(guess[i]);
			}

		}
		map<char, int> mp; // 记录原字符串中每个字符出现的次数 
		for (int i = 0; i < a_left.size(); ++i)
		{
			mp[a_left[i]]++;//计算去除命中之后 每个字符串的个数
		}
		/* 计算伪命中 */
		for (int i = 0; i < guess_left.size(); ++i)
		{
			if (mp.find(guess_left[i]) != mp.end())
			{
				miss++; // 遍历猜测的字符 若猜测的字符存在原字符串中 算一次伪命中
				mp[guess_left[i]]--; // 原字符串字符个数 减一
				if (mp[guess_left[i]] == 0)
					mp.erase(guess_left[i]); // 若原字符串个数为 0 删除原字符串的字符 防止伪命中 重复计算 
			}
		}
		vector<int> result;
		result.push_back(hit); result.push_back(miss);
		return result;
	}
};


发表于 2016-08-20 21:55:38 回复(0)
class Result {
public:
    vector<int> calcResult(string A, string guess) {
        // write code here
        vector<int> vec;
        if(A.length()<=0||guess.length()<=0) return vec; 
        int right=0;//猜中的个数
        int unright=0;//伪猜中的个数
        //统计猜中的个数
        int hashA[256]={0};
        int hashG[256]={0};
        int len=A.length();
        //统计猜中的个数
        for(int i = 0; i < len; i++)
        {
           if(A[i] == guess[i]) right++;
           else
           {
              hashA[A[i]]++;
              hashG[guess[i]]++;
           }
       }
       vec.push_back(right);
        //统计伪猜中的个数
       for(int i = 0; i < 256; i++)
       {
          if(hashA[i] > 0 && hashG[i] > 0) unright +=min(hashA[i], hashG[i]);
       }
        vec.push_back(unright);
        return vec;
    }
};

发表于 2016-08-18 22:21:19 回复(0)
class Result {
public:
    vector<int> calcResult(string A, string guess) {
        int t=0;
        vector <int> a(2,0);
        for(int i=0;i<4;i++){
             if(A[i]==guess[i]){
                  a[0]++;A[i]=guess[i]=(t++)+'0';
             }
             }
            for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                if(A[i]==guess[j]){
                   a[1]++;guess[j]=(t++)+'0';
                    break;
                }
          }
        }
        a[1]-=a[0];
        return a;
    }
};

发表于 2017-10-16 19:49:05 回复(1)
class Result {
public:
    vector<int> calcResult(string A, string guess) {
        // write code here
        string w, wGuess;
        vector<int > res(2,0);
		
        //统计猜中个数
        for (int i=0; i<A.length(); ++i)
        {
            if (A[i] == guess[i])
            {
                res[0]++;
            }
            else
            {
                w = w + A[i];
                wGuess += guess[i];
            }
        }
		//统计伪猜中个数
        for (int i=0; i<wGuess.length(); ++i)
        {
            int pos = w.find(wGuess[i]);
            if (pos >=0 && pos <w.length())
            {
                res[1]++;
                w[pos] = 'X';//防止重复计算
            }
        }
        return res;
    }
};

发表于 2017-04-01 16:18:06 回复(0)
先算出伪猜中,此时伪猜中中包含了猜中,再算出猜中,用伪猜中减去猜中就是最后正确的伪猜中个数
# -*- coding:utf-8 -*-

class Result:
    def calcResult(self, A, guess):
        t = ['R', 'Y', 'G', 'B']
        
        persudo = 0
        for i in t:
            persudo += min(A.count(i), guess.count(i))
        
        sum = 0
        for i in range(len(A)):
            if A[i] == guess[i]:
                sum += 1
                persudo -= 1
        return sum, persudo

发表于 2016-08-09 12:45:16 回复(0)
class Result {
public:
    vector calcResult(string A, string guess) {
        // write code here
        int hit=0,vague=0;
        for(int i=0;i<guess.size();++i)
        {
            if(i<A.size() && A[i]==guess[i])
            {
                hit++;
                A[i] = '#';
                guess[i] = '*';
            }
        }
        for(int i=0;i<guess.size();++i)
        {
            for(int j=0;j<A.size();++j)
            {
                if(j!=i && A[j]==guess[i])
                {
                    vague++;
                    A[j] = '#';
                    break;
                }
            }
        }
        vector ans;
        ans.push_back(hit);
        ans.push_back(vague);
        return ans;
    }
};
发表于 2020-08-03 23:22:08 回复(0)

Python用Counter

# -*- coding:utf-8 -*-
from collections import Counter as C
class Result:
    def calcResult(self, A, guess):
        res = [0, 0]
        res[0] = [a == b for a, b in zip(A, guess)].count(True)
        res[1] = sum([min(C(guess).get(k, 0), v) for k, v in C(A).items()]) - res[0]
        return res
编辑于 2018-12-26 19:16:02 回复(0)
class Result {
public:
    vector<int> calcResult(string A, string guess) {
        // write code here
        vector<int> res(2,0);
        int a[4]={0},b[4]={0};
        for(int i=0;i<4;i++) {
            if(A[i]==guess[i]) res[0]++;
            if(A[i]=='R') a[0]++;
            if(A[i]=='Y') a[1]++;
            if(A[i]=='G') a[2]++;
            if(A[i]=='B') a[3]++;
            if(guess[i]=='R') b[0]++;
            if(guess[i]=='Y') b[1]++;
            if(guess[i]=='G') b[2]++;
            if(guess[i]=='B') b[3]++;
        }
        for(int i=0;i<4;i++){
            if(a[i]!=0&&b[i]!=0&&a[i]<=b[i]) res[1]=res[1]+a[i];
            if(a[i]!=0&&b[i]!=0&&a[i]>b[i]) res[1]=res[1]+b[i];
        }
        res[1]=res[1]-res[0];
        return res;
    }
};
发表于 2017-10-06 14:03:15 回复(0)
代码比较长,但是思路比较简单清晰,先说一下我的,再去借鉴各位大神的代码;
我的思路:首先统计A的每个元素的个数(分别是r1,y1,b1,g1),统计guess中每个元素的个数(r3,y3,
g3,b3),然后在比较的时候,统计匹配成功的个数(r2,y2,b2,g2),这样匹配成功的个数就是res1=r2+
y2+b2+g2;
然后伪猜中的个数:就是四项求和,每一项取min(r1-r2,r3-r2)一次类推,得出结果
提醒大家,本题只有4个槽;
class Result {
public:
    vector<int> calcResult(string A, string guess) {
        vector<int> res;
        int res1=0;
        int res2=0;
        int r1=0,r2=0,r3=0;
        int y1=0,y2=0,y3=0;
        int g1=0,g2=0,g3=0;
        int b1=0,b2=0,b3=0;
        for(int i=0;i<A.length();i++)
            {
            if(A[i]=='R')
                r1++;
            else if(A[i]=='Y')
                y1++;
            else if(A[i]=='G')
                g1++;
            else
                b1++;
            if(A[i]==guess[i]&&A[i]=='R')
                r2++;
            else if(A[i]==guess[i]&&A[i]=='Y')
                y2++;
            else if(A[i]==guess[i]&&A[i]=='G')
                g2++;
            else if(A[i]==guess[i]&&A[i]=='B')
                b2++;
        }
        for(int i=0;i<guess.length();i++)
            {
            if(guess[i]=='R')
                r3++;
            else if(guess[i]=='Y')
                y3++;
            else if(guess[i]=='G')
                g3++;
            else
                b3++;
        }
        res1=r2+y2+b2+g2;
        int t1=min(r1-r2,r3-r2);
        int t2=min(y1-y2,y3-y2);
        int t3=min(g1-g2,g3-g2);
        int t4=min(b1-b2,b3-b2);
        res2=t1+t2+t3+t4;
        res.push_back(res1);
        res.push_back(res2);
        return res;
    }
};


编辑于 2017-09-27 11:57:22 回复(0)
import java.util.*;
/*
思路:转化到字符串考虑,猜中就是相同位置的字符相同,伪猜中就是不同位置的字符相同(不包含猜中部分)
即有不同位置字符相同的情况-猜中的情况=伪猜中
可以用到HashMap,切记:这种要计算字符出现次数的都可以用HashMap解决

*/
public class Result {
    public int[] calcResult(String A, String guess) {
        int []result ={0,0};//可以直接赋值
        HashMap<Character,Integer> map=new HashMap<>();
        char a[]=A.toCharArray();
        char g[]=guess.toCharArray();
 		for(int i=0;i<4;i++){
            if(a[i]==g[i]) result[0]++;
        }
        for(int i=0;i<4;i++){
            if(map.get(a[i])==null) map.put(a[i],1);
            else{
                int value =map.get(a[i]);
                map.put(a[i],value+1);
            }
        }
        for(int i=0;i<4;i++){
			if(map.get(g[i])!=null&&map.get(g[i])>0){
                int value=map.get(g[i]);
                map.put(g[i],value-1);
                result[1]++;
            }
        }
        result[1]=result[1]-result[0];
        return result;
    }
}
运行时间:80ms
占用内存:9044k

发表于 2017-07-05 19:59:02 回复(0)
#include<unordered_map>

class Result {
public:
    vector<int> calcResult(string A, string guess)
    {
        vector<int> res(2,0);
        unordered_map<char,int> count;
        for(int i = 0;i < 4;++i) 
        {
            if(A[i] == guess[i]) {++res[0];guess[i] = 'a';}
            else ++count[A[i]];
        }
        for(int i= 0;i < 4;++i)
        {
            if(guess[i] == 'a') continue;
            if(count[guess[i]] > 0)
            {
                ++res[1];
                --count[guess[i]];
            }
        }
        
        return res;
    }
};

发表于 2017-07-01 10:57:10 回复(0)
class Result:
    def calcResult(self, A, guess):
        B = {c: 0 for c in A}
        k, t, C = 0, 0, guess
        for i in range(len(A)):
            if A[i] == guess[i]:
                k += 1
            else:
                B[A[i]] += 1  # 给伪命中做准备

        for i in range(len(C)):
            if A[i] != C[i] and B.get(C[i], 0) > 0:
                t += 1
                B[C[i]] -= 1
        return [k, t]

发表于 2017-03-07 12:33:21 回复(0)
同下标的字符相同为猜中。我们把所有不猜中的字符做一个统计,然后计算A和guess具有相同的字符数有多少,加起来就是伪猜中的。    
vector<int> calcResult(string A, string guess) {
        // write code here
        vector<int> re(2,0);
        if(A.length()==0)
            return re;
        int result1=0,result2=0;
        int str1[26],str2[26];
        memset(str1,0,sizeof(str1));
        memset(str2,0,sizeof(str2));
        for(int i=0;i<A.length();i++)
        {
         if(A[i]==guess[i])
            {
               result1++;
               continue;
            }
            str1[A[i]-'A']++;
            str2[guess[i]-'A']++;
        }
        for(int i=0;i<26;i++)
        {
            if(str1[i]<str2[i])
                result2+=str1[i];
            else
                result2+=str2[i];
        }
        re[0]=result1;
        re[1]=result2;
        return re;
    }

发表于 2015-08-11 13:38:26 回复(0)
这道题解法非常多,我是模拟计算的。
发表于 2016-12-15 12:20:23 回复(0)

class Result {
public:
	vector<int> calcResult(string A, string guess) {
		std::map<char, int> ma, mg;
		int r = 0;

		for (auto i = 0u; i < A.size(); ++i) {
			if (A[i] == guess[i]) {
				++r;
			}
			else {
				++ma[A[i]];
				++mg[guess[i]];
			}
		}

		return { r, min(ma['R'], mg['R']) + min(ma['G'], mg['G']) + min(ma['B'], mg['B']) + min(ma['Y'], mg['Y']) };
	}
};


编辑于 2020-12-07 22:19:19 回复(0)
这题说的也太模糊了,什么叫猜对了颜色槽位不对
发表于 2020-08-07 12:14:59 回复(0)
class Result {
public:
    vector<int> calcResult(string A, string guess) {
        // write code here
        size_t size = A.size();
        int rightCnt = 0;
        int halfRightCnt = 0;
        int i = 0;
        map<char, int> strMap;
        for (; i < size; ++i) {
            if (A[i] == guess[i]) {
                ++rightCnt;
            } else {
                ++strMap[A[i]];
                guess.push_back(guess[i]);
            }
        }
        size = guess.size();
        for (; i < size; ++i) {
            if (strMap[guess[i]] != 0) {
                ++halfRightCnt;
                --strMap[guess[i]];
            }
        }
        vector<int> ret = {rightCnt, halfRightCnt};
        return ret;
    }
};

发表于 2020-07-27 22:04:39 回复(0)
巨麻烦,但是好懂
 public int[] calcResult(String A, String guess) {
        // write code here
        int [] res = new int[2];
        ArrayList<Character> deleted = new ArrayList<>();
        StringBuffer sb = new StringBuffer(A);
        StringBuffer sb2 = new StringBuffer(guess);

        int k =0;
        for(int i = 0; i < A.length(); i++){
            if(sb.charAt(i-k) == sb2.charAt(i-k)){
                res[0] ++;
                if(deleted.contains(sb.charAt(i-k))){
                    deleted.add(sb.charAt(i-k));
                }
                sb.deleteCharAt(i-k);
                sb2.deleteCharAt(i-k);
                k++;
            }
        }

        int length1 = sb.length();
        int length2 = sb2.length();
        k=0;
        for(int i = 0; i< length1; i++){
            for(int j = 0; j <length2 - k ; j++){
                if(sb.charAt(i-k) == sb2.charAt(j) && !deleted.contains(sb.charAt(i-k))){
                    res[1]++;
                    sb.deleteCharAt(i-k);
                    sb2.deleteCharAt(j);
                    k++;
                    break;
                }
            }
        }
        return res;
    }

发表于 2020-07-12 11:50:15 回复(0)
可能不是最简单的方法,但应该还是好理解的
首先不用管伪猜中,猜中只要对应位置一样就 ++
对于伪猜中,它的权限要比猜中小,就像题目说的,猜中不算伪猜中

所以我们对 A 字符进行计数(这里没有把猜中的字符加进去),因为没必要加,猜中并不属于伪猜中
在进行计算伪猜中的时候,要把猜中的位置跳过,因为它会影响伪猜中的计数

有一个伪猜中后,就把对应的字符个数减1,如果为0说明该字符不存在了
class Result {
public:
    vector<int> calcResult(string A, string guess) {
        // write code here
        int n = guess.size();
        int left = 0;
        map<char,int>mp;
        for(int i = 0;i<n;++i){
            if(A[i] == guess[i]){
                ++left;
            }else{
                mp[A[i]]++;
            }
        }
        int right = 0;
        for(int i = 0;i<n;++i){
            if(A[i] == guess[i])continue;
            if(mp[guess[i]] !=0){
                ++right;
                mp[guess[i]]--;
            }
        }
        return {left,right};
    }
};


发表于 2020-07-03 22:25:37 回复(0)

问题信息

难度:
66条回答 18248浏览

热门推荐

通过挑战的用户

查看代码