LintCode 1017: Similar RGB Color

本文介绍了一种高效算法,用于寻找最接近给定RGB颜色的简写颜色代码。通过分析颜色代码的特性,算法能快速确定最佳匹配,适用于颜色转换和优化场景。
  1. Similar RGB Color

In the following, every capital letter represents some hexadecimal digit from 0 to f.

The red-green-blue color “#AABBCC” can be written as “#ABC” in shorthand. For example, “#15c” is shorthand for the color “#1155cc”.

Now, say the similarity between two colors “#ABCDEF” and “#UVWXYZ” is -(AB - UV)^2 - (CD - WX)^2 - (EF - YZ)^2.

Given the color “#ABCDEF”, return a 7 character color that is most similar to #ABCDEF, and has a shorthand (that is, it can be represented as some “#XYZ”)

Example
Example 1:

Input: color = “#09f166”
Output: “#11ee66”
Explanation:
The similarity is -(0x09 - 0x11)^2 -(0xf1 - 0xee)^2 - (0x66 - 0x66)^2 = -64 -9 -0 = -73.
This is the highest among any shorthand color.
Example 2:

Input: color = “#010000”
Output: “#000000”
Explanation:
The similarity is -(0x01 - 0x00)^2 -(0x00 - 0x00)^2 - (0x00 - 0x00)^2 = -1 -0 -0 = -1.
This is the highest among any shorthand color.
Notice
color is a string of length 7.
color is a valid RGB color: for i > 0, color[i] is a hexadecimal digit from 0 to f
Any answer which has the same (highest) similarity as the best answer will be accepted.
All inputs and outputs should use lowercase letters, and the output is 7 characters.

解法1:

  1. 我们需要看3个2位数,这3个2位数可以看成彼此独立的,对于每个2位数,我们需要找到跟原2位数距离最近的最优解。
  2. 我们只需要看10位数即可。假设10位数是X,我们只需考虑X-1,X-1,X,X 和 X+1, X+1 3种可能,看哪种可能离原2位数距离最近。
class Solution {
public:
    /**
     * @param color: the given color
     * @return: a 7 character color that is most similar to the given color
     */
    string similarRGB(string &color) {
        int n = color.size();
        int C1 = 0, C2 = 0, C3 = 0;
        string S1, S2, S3;
        S1 = color.substr(1, 2);
        S2 = color.substr(3, 2);
        S3 = color.substr(5, 2);
        return '#' + similar(S1) + similar(S2) + similar(S3);
    }
    
private:
    string similar(const string S) {
        int ten = S[0] >= 'a' ? S[0] - 'a' + 10 : S[0] - '0';
        int digit = S[1] >= 'a' ? S[1] - 'a' + 10 : S[1] - '0';

        int C = ten * 16 + digit;
        int minDist = INT_MAX;
        int res_value = 0;
        string res_str = "";
        for (int i = -1; i <= 1; ++i) {
            if (ten == 0 && i == -1) continue;
            int candidate = (ten + i) * 16 + ten + i;
                int dist = abs(candidate - C);
            if (dist < minDist) {
                minDist = dist;
                res_value = candidate;
                if (ten + i >= 10) {
                    res_str = string(2, 'a' + ten + i - 10);
                } else {
                    res_str = string(2, '0' + ten + i);
                }
            }
        }
        return res_str;
    }
};

解法2:
参考思路见
https://www.cnblogs.com/grandyang/p/9296602.html
感觉很巧妙。解法1要每个2位数考虑3种情况,这个解法直奔主题,根据num/17和num%17与8的大小关系就可以推出最优解。
为什么是17呢?因为16进制的11,22,33,…ff之间就是相差17(10进制)。跟8比大小是为了就近匹配。

class Solution {
public:
    /**
     * @param color: the given color
     * @return: a 7 character color that is most similar to the given color
     */
    string similarRGB(string &color) {
        int n = color.size();
        int C1 = 0, C2 = 0, C3 = 0;
        string S1, S2, S3;
        S1 = color.substr(1, 2);
        S2 = color.substr(3, 2);
        S3 = color.substr(5, 2);
        return '#' + similar(S1) + similar(S2) + similar(S3);
    }
    
private:
    string similar(const string S) {
        int ten = S[0] >= 'a' ? S[0] - 'a' + 10 : S[0] - '0';
        int digit = S[1] >= 'a' ? S[1] - 'a' + 10 : S[1] - '0';
        int num = ten * 16 + digit;
    
        int new_digit = num / 17 + ((num % 17) > 8 ? 1 : 0);
        char new_digit_char = (new_digit >= 10) ? 'a' + new_digit - 10 : '0' + new_digit;
        
        return string(2, new_digit_char);
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值