首页 > 试题广场 >

查找兄弟单词

[编程题]查找兄弟单词
  • 热度指数:412408 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
定义一个单词的“兄弟单词”为:交换该单词字母顺序(注:可以交换任意次),而不添加、删除、修改原有的字母就能生成的单词。
兄弟单词要求和原来的单词不同。例如: ab 和 ba 是兄弟单词。 ab 和 ab 则不是兄弟单词。
现在给定你 n 个单词,另外再给你一个单词 x ,让你寻找 x 的兄弟单词里,按字典序排列后的第 k 个单词是什么?
注意:字典中可能有重复单词。

数据范围:,输入的字符串长度满足

输入描述:
输入只有一行。
先输入字典中单词的个数n,再输入n个单词作为字典单词。
然后输入一个单词x
最后输入一个整数k


输出描述:
第一行输出查找到x的兄弟单词的个数m
第二行输出查找到的按照字典顺序排序后的第k个兄弟单词,没有符合第k个的话则不用输出。
示例1

输入

3 abc bca cab abc 1

输出

2
bca
示例2

输入

7 cab ad abcd cba abc bca bca abc 3

输出

4
cab

说明

abc的兄弟单词有cab cba bca bca,所以输出4
经字典序排列后,变为bca bca  cab cba,所以第3个字典序兄弟单词为cab         
def is_brother(str1, str2):
    if str1 == str2:
        return False
    str1 = "".join(sorted(str1))
    str2 = "".join(sorted(str2))
    if str1 == str2:
        return True
    return False

while True:
    try:
        input_list = input().split()
        word_list, word, k = input_list[1:-2], input_list[-2], int(input_list[-1])
        brother_list = []
        for sub in word_list:
            if is_brother(word, sub):
                brother_list.append(sub)
        brother_list = sorted(brother_list)
        print(len(brother_list))
        print(brother_list[k-1])
    except:
        break

发表于 2022-07-18 00:26:32 回复(0)
const n = arr[0];
const x = arr[arr.length - 2];
const k = arr[arr.length - 1];
const newArr = [...arr]
const res = []
newArr.shift()
newArr.pop()
newArr.pop()
newArr.forEach(item=>{
    if(item.length === x.length && item.split('').sort().join('') === x.split('').sort().join('') && item !== x){
        res.push(item)
    }
})
console.log(res.length)
if(k-1<res.length){
    console.log(res.sort()[k-1])
}

发表于 2022-07-05 15:54:22 回复(0)
while True:
    try:
        data = input().split()
        bro_len = int(data[0])
        k = int(data[-1])
        temp = data[-2]
        words = data[1:-2]
        assert len(words) == bro_len, print('the length must be the same')
        bros = []
        for word in words:
            if sorted(word.lower()) == sorted(temp.lower()) and (not word==temp):
                bros.append(word)
                
        sorted_bros = sorted(bros, )
        
        print(len(bros))
        print(sorted_bros[k-1])        
    except:
        break

这个题比较简单,用暴力法即可解决。
先判断每个单词是否是模板单词的兄弟单词: if sorted(word.lower())==sorted(temp.lower()) and (not word==tempt)
然后将兄弟单词存储起来
最后将存储起来的兄弟单词按照字母顺序排列sorted(bors)

发表于 2022-06-25 16:09:06 回复(0)
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

class Solution
{
  public:
    void FindBrotherWord(const vector<string>& strs,const int& strs_size,const string& tar_str,const int& tar_index)
    {
        vector<string> brother_word;//存放所有兄弟单词的数组
        for(int i = 0; i < strs_size;i++)
        {
            //如果字符串个数相等,但是直接比较不等的情况
            if( (strs[i].size() == tar_str.size() ) && (strs[i] != tar_str))
            {
                string tar_tmp = tar_str;//暂时存放目标字符串
                string init_tmp = strs[i];//存放原字符串的字符
                sort(tar_tmp.begin(), tar_tmp.end());//两种分别排序后再判断是否相等
                sort(init_tmp.begin(), init_tmp.end());
                if(tar_tmp == init_tmp)//如果相等,保存到兄弟单词数组中
                {
                    brother_word.push_back(strs[i]);
                }
            }
        }
       sort(brother_word.begin(),brother_word.end());
        //查找索引
       if(tar_index > brother_word.size())//比兄弟个数要多
           cout << brother_word.size() << endl;
       else
       {
           cout << brother_word.size() << endl;
           cout << brother_word[tar_index-1] << endl;
       }
           
    }
};

int main()
{
    int i = 0;
    vector<string> strs;
    int strs_num = 0;//字典序中单词的个数
    string tar_str;//目标单词
    int tar_index; //要查找的兄弟单词在兄弟单词集的索引位置
    string str;
    while(cin >> str)
    {
        if(i == 0)
            strs_num = stoi(str);
        else if( i > 0 && i <= strs_num)
            strs.push_back(str);
        else if( i == (strs_num + 1))
            tar_str = str;
        else
            tar_index = stoi(str);
        i++;
    }
     Solution s;
     s.FindBrotherWord(strs,strs_num,tar_str, tar_index);
   
    //测试输入
    /*
    cout << strs_num << endl;
    for(auto p : strs)
    {
        cout << p << endl;
    }
    cout << tar_str << endl;
    cout << strs_index << endl;*/
    
   
    
    
    return 0;
}

发表于 2022-06-20 11:14:02 回复(0)
题目中的第一个  先输入字典中单词的个数n 有什么用?
def test(s: str):
    num, *lis, x, k = s.split(' ')
    k = int(k)
    result = sorted([i for i in lis if x != i and sorted(x) == sorted(i)])
    print(len(result))
    if len(result) >= k:
        print(result[k - 1])


if __name__ == '__main__':
    try:
        test(input())
    except EOFError:
        pass

发表于 2022-05-26 16:16:20 回复(0)
// 题目细节容易忽略,其他还好

import java.util.*;

public class Main {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        List<String> list = new ArrayList<>();

        while (n > 0) {
            list.add(sc.next());
            n--;
        }

        String target = sc.next();
        int k = sc.nextInt();

        List<String> brother = new ArrayList<>();
        int count = 0;
        for (String s : list) {
            if (!s.equals(target) && isBrotherWord(s, target)) {
                brother.add(s);
            }
        }
        
        Collections.sort(brother);
        
        System.out.println(brother.size());
        if (brother.size() >= k) {
            System.out.println(brother.get(k - 1));
        }
        
    }

    public static boolean isBrotherWord(String s1, String s2) {

        char[] chs1 = s1.toCharArray();
        char[] chs2 = s2.toCharArray();

        Arrays.sort(chs1);
        Arrays.sort(chs2);

        return String.valueOf(chs1).equals(String.valueOf(chs2));
    }
}

发表于 2022-05-21 18:11:24 回复(0)
while True:
    try:
        n,*lst,x,k = list(input().split())
        new = [i for i in lst if sorted(i) == sorted(x) and i!= x]
        new = sorted(new)
        print(len(new))
        if len(new)>=int(k):
            print(new[int(k)-1])
    except:
        break
        
发表于 2022-05-15 01:08:35 回复(1)
这个题目也太坑了,按字典序,我以为是按这个说的单词字典的原始顺序,原来结果是按abcd的这种字典序
发表于 2022-05-03 22:14:03 回复(0)
while True:
    try:
        list_a = list(input().split(sep=' '))
        word = list_a[-2]
        num = int(list_a.pop())
        new_list = []
        for i in list_a:
            if sorted(i) == sorted(word) and i != word:
                    new_list.append(i)
        res = sorted(new_list)
        print(len(res))
        print(res[num-1])
    except:
        break

发表于 2022-04-23 17:26:04 回复(0)
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        String [] word = str.split(" ");
        int len = word.length;
        String xWord = word[len -2];
        int k = Integer.parseInt(word[len -1]) ;
        String xSort = sortStr(xWord);
        // list保留所有的兄弟节点
        List<String> list = new ArrayList();
        for(int i=0;i<=len-3;i++){
            if(!xWord.equals(word[i]) 
               && xWord.length() == word[i].length()
               && xSort.equals(sortStr(word[i]))){
                list.add(word[i]);
            }
        }
        System.out.println(list.size());
        Collections.sort(list);
        if(list.size() > k ){
            System.out.print(list.get(k - 1));
        }
    }
    
    static String sortStr(String str){
        char [] chars = str.toCharArray();
        Arrays.sort(chars);
        return String.valueOf(chars);
    } 
}
发表于 2022-03-12 08:05:42 回复(0)

判断是否是兄弟字符的两种方法:

  1. 对两个字符串都按照同样的字典序排序,排序完后相同,则为兄弟字符
  2. 先使用dfs暴搜生成所有的兄弟字符数组表,再到其中查表找;
    比较后,两个方法的时间复杂度差不多
发表于 2022-03-09 23:23:01 回复(1)

当务之急是对输入的各个字符串,分辨出其中哪些字符串是给定字符串的兄弟单词。由题意可知,当两个字符串长度不等时,或两个字符串内容一摸一样时,它俩必然不是兄弟关系;当两个字符串长度相等,同时各索引位置对应的字符不全相等,但是构成各字符串的字符种类及其频次相等时,这两个字符串互为兄弟。
先从原始输入顺序的字符串序列中筛选出兄弟单词,并存入数组或数组链表等容器中,对容器中的字符串进行排序。如果对于容器存储元素的个数length,目标次序k有效,即k<=length,即可找到目标元素。理论上该方法可行,但对于本题提供的测试用例以及时间要求,运行结果表明该方法超出时间限制。分析一下,不难得知,因为这个处理过程不仅需要重新存储兄弟单词,还要对其进行排序,这两个任务不能同时进行。当输入的字符串数量很大时,当然要花费较多的时间,消耗较大的内存空间。但是,题目要求寻找有序的兄弟单词序列中的第k个兄弟单词,所以对兄弟单词序列进行排序是必需的。如果从原本就有序的字符串序列中依次筛查当前字符串是否为给定单词的兄弟单词,且同时计数,就可以在一次遍历过程结束时获悉目标结果。当计数值与k相等时,当前的字符串就是有序的第k个兄弟单词;如果直到遍历结束,计数值还小于k值,那么说明k值无效,没有找到有序的第k个兄弟单词。代码如下所示。

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        while (in.hasNext()) {
            int length = in.nextInt();

            String[] strArr = new String[length];
            for (int i = 0; i < length; i++) {
                strArr[i] = in.next();
            }

            String pattern = in.next();
            int k = in.nextInt();
            in.nextLine();

            getKthBroStr(pattern, strArr, k);
        }

        in.close();
    }

    private static void getKthBroStr(String pattern, String[] strArr, int k) {
        //查找strArr中pattern的兄弟单词顺序序列中的第k个

        Arrays.sort(strArr);
        //记录兄弟单词的个数
        int broCount = 0;
        //存储第k个兄弟单词
        String candidate = null;

        for (int i = 0; i < strArr.length; i++) {
            if (isBroStr(pattern, strArr[i])) {
                //如果数组中当前单词为兄弟单词,则broCount加一
                broCount++;
                //如果broCount值与k相等,即为目标
                if (k == broCount) candidate = strArr[i];
            }
        }

        System.out.println(broCount);
        if (candidate != null) {
            //如果找到了第k个兄弟单词,打印其,否则不打印
            System.out.println(candidate);
        }
    }

    private static boolean isBroStr(String pattern, String str) {
        //判断str是否为pattern的兄弟单词
        //如果两个字符串的长度不等,则不是兄弟
        if (pattern.length() != str.length()) return false;
        //如果两个字符串内容一摸一样,则不是兄弟,而是影子
        if (pattern.equals(str)) return false;

        char[] patternChars = pattern.toCharArray();
        char[] strChars = str.toCharArray();

        //对两个字符串对应的字符串组进行自然排序
        //如果排序后的两个数组各索引位置上对应的值相等,那这两个字符串互为兄弟,否则不是
        Arrays.sort(patternChars);
        Arrays.sort(strChars);

        return Arrays.equals(patternChars, strChars);
    }
}
发表于 2022-01-28 13:08:43 回复(0)
#include<iostream>
#include<set>
#include<string>
#include<vector>
#include<unordered_map>
std::pair<int, std::string> findBrother(std::vector<std::string>& arr,const std::string& findStr, int &k)
{
    size_t len = findStr.size();
    std::multiset<std::string> m;
    std::unordered_map<char, int> hash;
    for(auto &ch : findStr)
    {
        hash
[ch]++;
    }
    std::unordered_map<char, int> temp;
    
    for(auto & s: arr)
    {
        for(auto &ch : s)
        {
            temp
[ch]++;
        }
        bool flag = (temp == hash) ? true : false; 
        
        if(s != findStr && flag)
        {
            m.insert(s);
        }
        temp.clear();
    }
    
    int pos = static_cast<int>(m.size());
    std::string str;
    for(auto &s : m)
    {
        if(--k ==  0)
        {
            str = s;
            break;
        }
    }
    return std::make_pair(pos, str);
}

int main()
{
    int n;
    std::cin >>n;
    std::string str;
    std::vector<std::string> array(n);
    for(auto &s : array)
    {
        std::cin >>s;
    }
    std::string findStr;
    std::cin >>findStr;
    int k =0;
    std::cin >> k;
    std::pair<int, std::string> ret = findBrother(array, findStr, k);
    std::cout << ret.first << std::endl;
    std::cout << ret.second << std::endl;
    return 0;
}

编辑于 2022-01-19 16:14:45 回复(1)
算不上困难的题目,重点在于用排序的方法判断是否为兄弟单词
while True:
    try:
        s=input().split()
        m=int(s[0])
        t=list(s[len(s)-2])
        k=int(s[len(s)-1])
        s.pop(0)
        s.pop(len(s)-1)
        s.pop(len(s)-1)

        bro=[]
        for x,i in enumerate(s):
            i=list(i)
            if i!=t:
                if sorted(i)==sorted(t):
                    bro.append(s[x])

        print(len(bro))
        bro.sort()
        if k<=len(bro):
            print(bro[k-1])
    except:
        break

发表于 2021-12-06 18:38:17 回复(0)
判断是否兄弟单词
1. 单词长度不一致, false
2. 单词相等, false
3. 因为可以任意次交换,并且同一个单词中有相同字母的可能性,不能通过判断单词contains来判断。这里再次使用了全排列的算法。将需要判断的单词toCharArray后进行全排列,全排列结果中有等于target单词的,则是兄弟单词。
import java.util.*;

public class HJ27 {
    private static  String target;
    private  static List<String> brothers = new ArrayList<>();
    private static boolean flag = false;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            String str = sc.nextLine();
            String[] strArr = str.split(" ");
            int n = Integer.valueOf(strArr[0]);

            int k = Integer.valueOf(strArr[strArr.length-1]);

            target = strArr[strArr.length -2];


            for (int i =1; i<= n; i++) {
                String item = strArr[i];
                if (item.length() != target.length() || item.equals(target)) {
                    continue;
                }
                isBrother(item, 0);
                if(flag) {
                    brothers.add(item);
                }
                flag = false;
            }
            System.out.println(brothers.size());
            if (brothers.size() >= k) {
                brothers.sort((s1,s2) -> {
                    return s1.compareTo(s2);
                });
                System.out.println(brothers.get(k-1));
            }

            brothers.clear();
        }
    }

    private static void isBrother(String item, int m) {
        if (m == item.length() - 1) {
            if (item.equals(target)) {
                flag = true;
            }
        }
        // 对target的字母进行全排列
        for (int i=m; i < item.length();i++) {
             item = swap(item.toCharArray(), i, m);
             isBrother(item, m + 1);
             item = swap(item.toCharArray(), i, m);
        }
    }

    private static String swap(char[] arr, int m , int n) {
        char temp = arr[m];
        arr[m] = arr[n];
        arr[n] = temp;
        return String.valueOf(arr);
    }
}


发表于 2021-08-18 22:31:52 回复(0)
#include <stdio.h>
#include <string.h>

int is_bro_str(char* a, char* b)
{
    if (!strcmp(a, b))
        return 0;
    int alen = strlen(a);
    int blen = strlen(b);
    if (alen != blen)
        return 0;

    char c['z' - 'A'] = { 0 };
    char d['z' - 'A'] = { 0 };
    for (int i = 0; i < alen; i++) {
        c[a[i] - 'A']++;
        d[b[i] - 'A']++;
    }
    for (int i = 0; i < 'z' - 'A'; i++) {
        if (c[i] != d[i])
            return 0;
    }
    return 1;
}

int main()
{
    int n;
    while (scanf("%d", &n) != EOF) {
        char str[n][1000];
        char bro[n][1000];
        char pstr[1000] = { 0 };

        for (int i = 0; i < n; i++) {
            scanf("%s", str[i]);
        }

        int k;
        scanf("%s", pstr);
        scanf("%d", &k);

        int count = 0;
        for (int i = 0; i < n; i++) {
            if (is_bro_str(pstr, str[i])) {
                strcpy(bro[count], str[i]);

                // 插入排序
                int j = count - 1;
                for (; j >= 0; j--) {
                    if (strcmp(str[i], bro[j]) < 0) {
                        strcpy(bro[j + 1], bro[j]);
                    }
                    else {
                        break;
                    }
                }
                strcpy(bro[j + 1], str[i]);
                count++;
            }
        }
        printf("%d\n", count);
        if (k <= count && k > 0) {
            printf("%s\n", bro[k - 1]);
        }
    }
    return 0;
}

发表于 2021-08-11 00:41:11 回复(0)
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            //输入处理
            String[] s = sc.nextLine().split("\\ ");
            int n = Integer.parseInt(s[0]);
            String x = s[s.length-2];
            int k = Integer.parseInt(s[s.length-1]);

            //提供单词中所有x的兄弟单词放入集合
            ArrayList<String> list = new ArrayList<>();
            for(int i=1; i<=n; i++){
                if(isBrother(s[i], x)) list.add(s[i]);
            }

            //输出结果
            int size = list.size();
            System.out.println(list.size());
            if(size>=k){
                Collections.sort(list);
                System.out.println(list.get(k-1));
            }
        }
    }
    
    private static boolean isBrother(String s, String x){
        //长度不等或字符串相等,直接false
        if(s.length()!=x.length() || s.equals(x)) return false;
        
        //转为字符数组排序后,转为字符串相等则是兄弟单词
        char[] c1 = s.toCharArray();
        char[] c2 = x.toCharArray();
        Arrays.sort(c1);
        Arrays.sort(c2);
        return (new String(c1)).equals(new String(c2));
    }
}

发表于 2021-08-03 20:18:49 回复(0)
#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

bool isBrother(string str, string s)
{
    if (str.size() == s.size())
    {
        if (str == s)
            return false;
        sort(str.begin(), str.end());
        sort(s.begin(), s.end());
        if (str == s)
            return true;
    }
    return false;
}

int main()
{
    int n;
    while (cin >> n)
    {
        // set元素唯一,不能在此题中使用
        multiset<string> s;
        // 将数据放入multiset自动按照字典排序
        for (int i = 0; i < n; i++)
        {
            string tmp;
            cin >> tmp;
            s.insert(tmp);
            tmp.clear();
        }
        string word;
        int k;
        cin >> word >> k;
        // 记录兄弟单词,在存放数据的时候直接按照字典序,不需要手动排序
        vector<string> ans;
        for (auto& e : s)
        {
            if (isBrother(e, word))
                ans.push_back(e);
        }
        cout << ans.size() << endl;
        // 下标从0开始,所以访问k-1的位置
        if (k <= ans.size())
            cout << ans[k - 1] << endl;
    }
    return 0;
}



发表于 2021-06-16 18:21:12 回复(0)
循环单词列表,在跳过目标单词本身的情况下,挨个判断当前单词的字符计数是否与目标单词相同,相同的话就是兄弟单词。
需要注意:只有存在兄弟单词且k不大于兄弟单词个数的情况下才输出兄弟单词的个数和字典排名第k的兄弟单词,否则只输出兄弟单词个数。
from collections import defaultdict

while True:
    try:
        arr = input().strip().split()
        n = int(arr[0])
        words, word, k = arr[1: n + 1], arr[n + 1], int(arr[-1])
        mp = defaultdict(lambda: 0)
        for alpha in word:
            mp[alpha] += 1
        word_list = []     # 兄弟单词列表
        for w in words:
            if w == word:   # 跳过自己
                continue
            counter = defaultdict(lambda: 0)
            for alpha in w:
                counter[alpha] += 1
            if counter == mp:    # 字符计数情况相同,是兄弟单词
                word_list.append(w)
        num = len(word_list)
        if num and k <= num:
            print(num)
            print(sorted(word_list)[k - 1])
        else:
            print(num)
    except:
        break

发表于 2021-03-29 17:49:35 回复(0)
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
// 判定两个单词是否是兄弟单词
bool isBrother(string str, string s){
    // 1. 先判定长度是否相同. 不相同的一定不是兄弟单词
    if(str.size() == s.size()){
        // 2. 再判定字符串是否完全相同. 相同了也不算兄弟单词
        if(str == s) return false;
        // 3. 将两个单词排序. 排序后相同才是兄弟单词(因此参数不能用 const&)
        // 这一步很关键
        sort(str.begin(), str.end());
        sort(s.begin(), s.end());
        if(str == s) return true;
    }
    return false;
}
int main(){
    int num;
    while(cin >> num){
        string str;
        string word,s;
        int index;
        vector<string> vs;
        // 读取字典中的单词, 把字典放到 vs 中.
        for(int i = 0; i < num; ++i){
            cin >> str;
            vs.push_back(str);
        }
        // [注意!!] 题意说的是 "字典", 因此要将里面的单词按照字典序排序~否则得到的 k 会存在问题.
        sort(vs.begin(), vs.end());
        // 读入要判定的词和k
        cin >> word;
        cin >> index;
        int counts = 0; 
        // 统计字典中存在多少个兄弟单词.
        for(int i = 0; i < num; ++i){
            if(isBrother(word, vs[i])){
                counts ++;
                // 将第 k 个兄弟单词保存到 s 中.
                if(counts == index)
                    s = vs[i];
            }
        }
        // 最后输出结果
        if(!vs.empty())
            cout << counts << endl;
        if(counts >= index) cout << s << endl;
    }
    return 0;
}

发表于 2020-09-06 15:23:14 回复(0)