根据模式串构造最小数字

简介: 根据模式串构造最小数字

说在前面

🎈不知道大家对于算法的学习是一个怎样的心态呢?为了面试还是因为兴趣?不管是出于什么原因,算法学习需要持续保持。

题目描述

给你下标从 0 开始、长度为 n 的字符串 pattern ,它包含两种字符,'I' 表示 上升'D' 表示 下降

你需要构造一个下标从 0 开始长度为 n + 1 的字符串,且它要满足以下条件:

  • num 包含数字 '1''9' ,其中每个数字 至多 使用一次。
  • 如果 pattern[i] == 'I' ,那么 num[i] < num[i + 1]
  • 如果 pattern[i] == 'D' ,那么 num[i] > num[i + 1]

请你返回满足上述条件字典序 最小 的字符串 **num

示例 1:

输入: pattern = "IIIDIDDD"
输出: "123549876"
解释: 下标 0 ,1 ,2 和 4 处,我们需要使 num[i] < num[i+1] 。
下标 3 ,5 ,6 和 7 处,我们需要使 num[i] > num[i+1] 。
一些可能的 num 的值为 "245639871" ,"135749862" 和 "123849765" 。
"123549876" 是满足条件最小的数字。
注意,"123414321" 不是可行解因为数字 '1' 使用次数超过 1 次。

示例 2:

输入: pattern = "DDD"
输出: "4321"
解释:
一些可能的 num 的值为 "9876" ,"7321" 和 "8742" 。
"4321" 是满足条件最小的数字。

提示:

  • 1 <= pattern.length <= 8
  • pattern 只包含字符 'I''D'

思路分析

首先我们还是要先来理解一下题意,题目会给出一串只包含ID两种字符的字符串,其中'I' 表示 上升,即如果 pattern[i] == 'I' ,那么 num[i] < num[i + 1]'D' 表示 下降,即如果 pattern[i] == 'D' ,那么 num[i] > num[i + 1] 。我们需要构造一个下标从 0 开始长度为 n + 1 的字符串,字符串应该满足题目给出参数的升降规则,而且是满足上述条件字典序 最小 的字符串 num

暴力搜索

我们来看一下数据范围:1 <= pattern.length <= 8,最多只有9位数,所以我们其实是可以通过暴力搜索来得出答案的:

回溯模拟,遍历到位置i时,我们查看在1-9中找到一个数,满足pattern[i],继续往下拼接。当遍历到结尾,我们找到了一个满足条件的数字,维护最小的即可。

var smallestNumber = function(pattern) {
    const used = new Array(10).fill(false);
    let ans;
    function dfs(str, i) {
        if (i >= pattern.length) {
            if (!ans || Number(str) < Number(ans)) {
                ans = str
            }
            return;
        }
        const v = pattern[i];
        const prev = str[i];
        for (let j = 1; j < 10; j++) {
            if (used[j]) continue;
            const bool = v === 'I' ? j > +prev : j < +prev;
            if (bool) {
                used[j] = true;
                dfs(str + j, i + 1)
                used[j] = false;
            }
        }
    }
    for (let i = 1; i < 10; i++) {
        used[i] = true;
        dfs(`${i}`, 0)
        used[i] = false;
    }
    return ans;
};

贪心,找规律

那么还有没有其他的方法呢?我们可以从下面几个点入手考虑一下是不是可以使用贪心思想来进行解答。

  • 字符串字典序最小

要使整个字符串的字典序最小,我们应该尽可能的将数值小的数字放在前面。

  • 当前下标位置最大取值

当前位置的最大取值与给出pattern相对位置的字符有关,如果当前位置是I(上升的),我们可以直接取当前没用过的数字的最小值即可,如果是D(下降的),那我们则需要预留出给其下降的空间,如DD,说明它需要连续下降两次,所以我们需要预留出一个数字。也就是说我们当前位置的取值会受到pattern相对位置后面连续D字符的数量的影响,所以我们只需要统计一下连续D的后缀个数即可,具体代码如下:

/**
 * @param {string} pattern
 * @return {string}
 */
 var smallestNumber = function(pattern) {
     let dd = new Array(pattern.length).fill(0);
     for(let j = pattern.length - 1; j >= 0 ; j--){
         if(j == pattern.length - 1) pattern[j] == 'D' ? dd[j] = 1 : '';
         else{
             if(pattern[j] == 'D') dd[j] = dd[j + 1] + 1;
         }
     }
     let res = '',ind = 0;
     for(let i = 0; i < pattern.length; i++){
         res += res.length + 1 + dd[i] - ind;
         if(dd[i]) ind++;
         else ind = 0;
     }
     if(pattern[pattern.length - 1] == 'I'){
         res += res.length + 1;
     }else{
        res += parseInt(res[res.length - 1]) - 1;
     }
     return res;
};

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

目录
相关文章
给定一个正整数N,将其表示为数字1,3,7,15相加的形式输出。请编码找出使上述数字出现的总次数最少(每个数字可以重复使用)的组合。
给定一个正整数N,将其表示为数字1,3,7,15相加的形式输出。请编码找出使上述数字出现的总次数最少(每个数字可以重复使用)的组合。
|
6月前
|
安全 C语言 C++
数与字符串相互转化
数与字符串相互转化
32 1
|
7月前
对任意给定的两个正整数,100<n<m<1000,计算这两个数之间所有素数和,包含m,n自身
对任意给定的两个正整数,100<n<m<1000,计算这两个数之间所有素数和,包含m,n自身
56 0
对任意给定的两个正整数,100<n<m<1000,计算这两个数之间所有素数和,包含m,n自身
|
7月前
字符串,每个里面包含0-N个数字,如3,8,2,编写函数,将两个这样的字符串合并,并且输出的字符串里面没有重复的数字,并从大到小排列.
字符串,每个里面包含0-N个数字,如3,8,2,编写函数,将两个这样的字符串合并,并且输出的字符串里面没有重复的数字,并从大到小排列.
39 0
|
7月前
输入一个字符串,统计其中字符A的数量并且输出,输入共有一行,为一个不带空格的字符串(其中字符数不超过100),输出一行,包含一个整数,为输入字符串中的A的数量
输入一个字符串,统计其中字符A的数量并且输出,输入共有一行,为一个不带空格的字符串(其中字符数不超过100),输出一行,包含一个整数,为输入字符串中的A的数量
题目:下列给定程序中函数fun的功能是:从p所指字符串中找出ASCII码值最大的字符,将其放在第一个位置上,并将该字符前的原字符向后顺序移动。
题目:下列给定程序中函数fun的功能是:从p所指字符串中找出ASCII码值最大的字符,将其放在第一个位置上,并将该字符前的原字符向后顺序移动。
109 0
统计二进制中1的个数,,,写一个函数,返回参数二进制中1的个数 写一个代码判断一个数字是不是2的n次方
统计二进制中1的个数,,,写一个函数,返回参数二进制中1的个数 写一个代码判断一个数字是不是2的n次方
137 0

热门文章

最新文章