目录
重排字符串(贪⼼+构造)
题目解析
1.题目链接:登录—专业IT笔试面试备考平台_牛客网
2.题目描述
题目描述
小红拿到了一个只由小写字母组成的字符串。她准备把这个字符串重排(只改变字母的顺序,不改变数量)
重排后小红想让新字符串不包含任意两个相同的相邻字母。
你能帮帮她吗?输入描述:
第一行一个正整数 nnn ,代表字符串的长度。 (1≤n≤105)(1 \leq n \leq 10^5)(1≤n≤105)
第二行为一个长度为 nnn 的、只由小写字母组成的字符串。输出描述:
如果可以完成重排,请在第一行输出一个“yes”,第二行输出重排后的字符串。如果有多个正解,输出任意即可。
如果不能重排,则直接输出“no”示例1
输入
5 aaaaa
5
aaaaa输出
no
no
示例2
输入
7 aabbccc
7
aabbccc输出
yes cabcabc
yes
cabcabc
讲解算法原理
解法:
算法思路:
⼒扣有⼀道《距离相等的条形码》和这道题是差不多滴~
编写代码
c++算法代码:
#include <iostream>
using namespace std;
const int N = 100010;
int n;
char s[N];
char ret[N];
int main()
{
cin >> n >> s;
int hash[26] = { 0 }; // 统计每个字符的频次 int maxIndex, maxCount = 0; for(int i = 0; i < n; i++) {
if(maxCount < ++hash[s[i] - 'a'])
{
maxCount = hash[s[i] - 'a']; maxIndex = s[i] - 'a'; }
}
if(maxCount > (n + 1) / 2) cout << "no" << endl; else
{
cout << "yes" << endl; int index = 0;
// 先去摆放出现次数最多的 while(maxCount--) {
ret[index] = maxIndex + 'a'; index += 2;
}
// 处理剩下的
for(int i = 0; i < 26; i++)
{
if(hash[i] && i != maxIndex)
{
while(hash[i]--)
{
if(index >= n) index = 1; ret[index] = i + 'a'; index += 2;
}
}
}
// 打印结果
for(int i = 0; i < n; i++) cout << ret[i]; cout << endl;
}
return 0;
}
java算法代码:
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in); int n = in.nextInt(); char[] s = in.next().toCharArray(); char maxChar = '0'; int maxCount = 0; int[] hash = new int[26];
// 找出现次数最多的字符以及次数 for(int i = 0; i < n; i++) {
char ch = s[i]; if(++hash[ch - 'a'] > maxCount) { maxChar = ch; maxCount = hash[ch - 'a']; }
}
// 判断是否能重排
if(maxCount > (n + 1) / 2)
{
System.out.println("no");
}
else
{
System.out.println("yes"); char[] ret = new char[n]; int i = 0; // 重新排列
// 1. 先处理出现次数最多的字符 while(maxCount-- != 0) {
ret[i] = maxChar; i += 2;
}
// 2. 处理剩下的字符
for(int j = 0; j < 26; j++)
{
if(hash[j] != 0 && (char)(j + 'a') != maxChar)
{
while(hash[j]-- != 0)
{ if(i >= n) {
i = 1;
} ret[i] = (char)(j + 'a'); i += 2; } }
}
for(int j = 0; j < n; j++)
{
System.out.print(ret[j]);
}
}
}
}
乒乓球筐(哈希)
题目解析
1.题目链接:乒乓球筐__牛客网
2.题目描述
nowcoder有两盒(A、B)乒乓球,有红双喜的、有亚力亚的……现在他需要判别A盒是否包含了B盒中所有的种类,并且每种球的数量不少于B盒中的数量,该怎么办呢?
输入描述:
输入有多组数据。
每组数据包含两个字符串A、B,代表A盒与B盒中的乒乓球,每个乒乓球用一个大写字母表示,即相同类型的乒乓球为相同的大写字母。
字符串长度不大于10000。输出描述:
每一组输入对应一行输出:如果B盒中所有球的类型在A中都有,并且每种球的数量都不大于A,则输出“Yes”;否则输出“No”。
示例1
输入
ABCDFYE CDE<br/>ABCDGEAS CDECDE
输出
Yes<br/>No
讲解算法原理
解法:
算法思路:
简单查询题⽬,可以⽤哈希表帮助我们解决。
编写代码
c++算法代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1, s2;
while(cin >> s1 >> s2) // 未知组数的输⼊ {
int hash[26] = { 0 }; for(auto ch : s1) hash[ch - 'A']++; bool ret = true; for(auto ch : s2) { if(--hash[ch - 'A'] < 0) { ret = false; break;
}
}
cout << (ret ? "Yes" : "No") << endl;
}
return 0;
}
java算法代码:
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in); while(in.hasNext()) // 未知组数的输⼊ {
char[] s1 = in.next().toCharArray(); char[] s2 = in.next().toCharArray(); int[] hash = new int[26];
for(int i = 0; i < s1.length; i++)
{
hash[s1[i] - 'A']++;
}
boolean ret = true; for(int i = 0; i < s2.length; i++) { if(--hash[s2[i] - 'A'] < 0) { ret = false; break; }
}
System.out.println(ret ? "Yes" : "No");
}
}
}