【华为OD题库-061】关联子串-java

题目

给定两个字符串str1和str2,
str1进行排列组合,只要有一个为str2的子串则认为str1是str2的关联子串,请返回子串在str2的起始位置,若不是关联子串则返回-1。
示例1
输入输出示例仅供调试,后台判题数据一般不包含示例输入
abc efghicbaili
输出
5
示例2
输入输出示例仅供调试,后台判题数据一般不包含
示例输入
abc efghiccaii
输出
-1

思路

题目隐含的条件应该是找到第一个匹配的子串。否则,可能有多种解
比如对于输入:cbcd adbccdebed。cbcd的排列组合可能有:dbcc,bccd等,如果先遍历的bccd那么得到的答案是2,如果先遍历dbcc得到的是1。

本题可以从排列组合和滑动窗口两个角度考虑解决

排列组合

组合模板见:【JAVA-排列组合】一个套路速解排列组合题。不赘述

找到str1所有的排列情况,依次遍历其是否是str2的子串。

滑动窗口

维护一个长度和str1等长的滑动窗口,判断窗口内的值是否和str1匹配,如果匹配,直接输出窗口左边界,否则右移滑动窗口
判断窗口内是否和str1匹配:每个字符数出现次数相等或者将两者按照同一逻辑排序,排序后相等则两者匹配

题解

排列组合解法

package hwod;

import java.util.*;

public class RelationSubStr {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] input = sc.nextLine().split(" ");
        String str1 = input[0];
        String str2 = input[1];
        System.out.println(relationSubStr(str1, str2));
    }

    private static List<String> res = new ArrayList<>();//存放字符串1所有可能的排列

    // 暴力解法
    private static int relationSubStr(String str1, String str2) {
        char[] chars = str1.toCharArray();
        int[] used = new int[str1.length()];
        dfs(chars, "", used);
        int ans = str2.length();
        for (int i = 0; i < res.size(); i++) {
            int tmp = str2.indexOf(res.get(i));
            if (tmp != -1 && tmp < ans) {
                ans = tmp;
            }
        }
        return ans == str2.length() ? -1 : ans;
    }

    private static void dfs(char[] chars, String str, int[] used) {
        if (str.length() == chars.length) {
            res.add(str);
        }
        for (int i = 0; i < chars.length; i++) {
            if (used[i] == 1) continue;
            str += chars[i];
            used[i] = 1;
            dfs(chars, str, used);
            str = str.substring(0, str.length() - 1);
            used[i] = 0;
        }
    }
}

滑动窗口解法

package hwod;

import java.util.*;

public class RelationSubStr {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] input = sc.nextLine().split(" ");
        String str1 = input[0];
        String str2 = input[1];
        System.out.println(relationSubStr(str1, str2));
    }

    //滑动窗口
    private static int relationSubStr(String str1, String str2) {
        Map<Character, Integer> map1 = new HashMap<>();
        Map<Character, Integer> map2 = new HashMap<>();
        for (int i = 0; i < str1.length(); i++) {
            map1.put(str1.charAt(i), map1.getOrDefault(str1.charAt(i), 0) + 1);
        }
        int size = str1.length();
        int k = 0;
        while (k < str2.length()) {
            map2.put(str2.charAt(k), map2.getOrDefault(str2.charAt(k), 0) + 1);
            int i = k - size + 1;
            if (i < 0) {
                k++;
                continue;
            }
            if (checked(map1, map2)) {
                return i;
            }
            map2.put(str2.charAt(i), map2.getOrDefault(str2.charAt(i), 0) - 1);
            k++;

        }
        return -1;
    }

    private static boolean checked(Map<Character, Integer> map1, Map<Character, Integer> map2) {
        for (Character key : map1.keySet()) {
            if (!map2.containsKey(key)) return false;
            if (!map1.get(key).equals(map2.get(key))) return false;
        }
        return true;
    }
}

推荐

如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。

说明

本专栏所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/qq_31076523/article/details/134176793。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值