【每周n题】字符串哈希,欧拉图算法,24点回溯

终于还是开学了,还是坚持每日一t的节奏,只是更新可能不是很及时了

214.最短回文串

在这里插入图片描述

暴力的算法就是进行枚举,找到从头开始最长的一个回文字符串。然后反转后缀添加上去。
这里主要注意一下语言:

  • s.substring(begin, end) 截取字符串
  • new StringBuilder(s.substring(sh)).reverse().append(s).toString();熟练使用StringBuffer
class Solution {
    public String shortestPalindrome(String s) {
        int sh = 0;
        for (int i = s.length(); i>0; i--){
            String sub = s.substring(0,i);
            if (isPali(sub)) {
                sh = i;
                break;
            }
        }
        return new StringBuilder(s.substring(sh)).reverse().append(s).toString();
    }
    public boolean isPali(String s){
        int n = s.length();
        int l = 0, r = n-1;
        while (r>=l){
            if (s.charAt(l) != s.charAt(r)) return false;
            l++;
            r--;
        }
        return true;
    }
}

但是这种方法的复杂度太高,还可以采用字符串哈希的方法。这种方法第一次用到,比较神奇。基本的思路是把每个字符看成一个base进制的,然后从前往后遍历,如果正序和逆序一样,等价于两个数字一样。这里需要注意,由于进制太大,整型无法存放,因此我们取模。

一般来说,我们选取一个大于字符集大小(即字符串中可能出现的字符种类的数目)的质数作为 base,再选取一个在字符串长度平方级别左右的质数作为mod,产生哈希碰撞的概率就会很低。

class Solution {
    public String shortestPalindrome(String s) {
        int base = 131, mod = 1000000007;
        int l = 0, r = 0;
        int mul = 1, best = -1;
        for (int i = 0; i < s.length(); i++){
            l = (int) (((long) l * base + s.charAt(i)) % mod);
            r = (int) ((r + (long) mul * s.charAt(i)) % mod);
            if (l == r) best = i; // best存储了最后依次相等的位置,因此在反转时候需要从best+1开始
            mul = (int) ((long) mul * base % mod);
        }
        return new StringBuffer(s.substring(best+1)).reverse().append(s).toString();
    }
}

对于字符串哈希还有一个典型题目字符串哈希

332.重新安排行程

在这里插入图片描述

很明显是一道图论的题目,有两个特点,一个是不重复的经过每一条路线,另外一个是按照字母序的方法。

对于第一个特点,其实涉及到一个我不是很熟悉的知识点,欧拉图。

在这里插入图片描述在这里插入图片描述

对于欧拉图的题目我们一般采用的算法就是Hierholzer算法。基本思路是从起点开始依次进行dfs搜索,每次途径一条边时都要删除,将没有任何邻居的孤立点加入栈中。最后将整个栈反转即可。

在这里插入图片描述

class Solution {
    private Map<String, PriorityQueue<String>> map;
    private List<String> ans; 
    public List<String> findItinerary(List<List<String>> tickets) {
        map = new HashMap<>();
        ans = new LinkedList<>();
        for (List<String> cur:tickets){
            String fro = cur.get(0), to = cur.get(1);
            if (!map.containsKey(fro)) map.put(fro, new PriorityQueue<String>());
            map.get(fro).add(to);
        }
        dfs("JFK");
        Collections.reverse(ans);
        return ans;
    }
    public void dfs(String cur){
    //双重判断,存在这个key并且时孤立节点
        while (map.containsKey(cur) && map.get(cur).size()>0){
            String next = map.get(cur).poll();
            dfs(next);
        }
        ans.add(cur);
    }
}

491.递增子序列

在这里插入图片描述

也是一道可以考虑到字符串哈希的题目。首先因为要枚举子序列,我们考虑到使用未的方法,然后我们为了去重不同的序列,对每一个序列进行哈希,并且判断每一个数列是不是递增的。

class Solution {
    // 这里的ArrayList需要声明内部的空间
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    Set<Integer> set = new HashSet<>();
    List<Integer> temp = new ArrayList<>();
    int n;
    public List<List<Integer>> findSubsequences(int[] nums) {
        n = nums.length;
        for (int i = 1 ; i<(1<<n); i++){
            newnum(i, nums);
            int code = gethash();
            if (check() && !set.contains(code)){
               ans.add(new ArrayList<Integer>(temp)); 
               set.add(code);
            }
        }
        return ans;
    }
    
    public void newnum(int num, int[] nums){
        temp.clear();
        for (int i = 0; (num>>i)>0; i++){
            if (((num>>i)&1) == 1) {
                temp.add(nums[i]);
            }
        }
    }

    public boolean check(){
        int m = temp.size();
        for (int i = 1; i<m;i++){
            if (temp.get(i)<temp.get(i-1))return false;
        }
        return temp.size() >= 2;
    }

    public int gethash(){
         base的选择需要大于总的可能性
        int mod = 1000000007, base = 263;
        int left = 0;
        for (int i = 0; i<temp.size();i++){
             因为范围是-100,100,所以我们能都给平移到正的范围
            left = (int)((temp.get(i)+101+(long)left*base)%mod);
        }
        return left;
    }
}

679.24点游戏

在这里插入图片描述

主要思想还是进行回溯,依次枚举每两个数字之间可能的操作。

class Solution {
    static final int TARGET = 24;
    static final double EPSILON = 1e-6;
    static final int ADD = 0, MULTIPLY = 1, SUBTRACT = 2, DIVIDE = 3;

    public boolean judgePoint24(int[] nums) {
        List<Double> list = new ArrayList<>();
        for (int i = 0; i<nums.length;i++) list.add((double)nums[i]);
        return solve(list);
    }

    public boolean solve(List<Double> list){
        if (list.size() == 1) return (Math.abs(list.get(0) - TARGET)<EPSILON);
        if (list.size() == 0) return false;
        int n = list.size();
        for(int i = 0; i<n; i++){
            for (int j = 0 ;j<n;j++){
                if (i!=j){
                    List<Double> list2 = new ArrayList<>();
                    for (int k = 0; k<n;k++){
                        if (k!=i && k!=j) list2.add(list.get(k));
                    }
                    for (int k = 0; k<4;k++){
                        if (i>j && k<2) continue;
                        if (k == 0) list2.add(list.get(i)+list.get(j));
                        else if (k == 1) list2.add(list.get(i)*list.get(j));
                        else if (k == 2) list2.add(list.get(i)-list.get(j));
                        else if (k == 3) {
                            list2.add(list.get(i)/list.get(j));
                        }
                        // 回溯的关键
                        if (solve(list2)) return true;
                        list2.remove(list2.size()-1);
                    }
                }
            }
        }
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
字符串匹配算法是一种用来查找一个字符串(即目标串)在另一个字符串(即模式串)中的出现位置的算法。其中,KMP算法是一种比较常用的字符串匹配算法。 KMP算法的核心思想是通过利用模式串中已经匹配过的信息,来尽量减少目标串和模式串的比较次数,从而提高匹配效率。它利用一个最长公共前缀和最长公共后缀数组,记录模式串中已经匹配成功的前缀和后缀的长度。通过根据这些信息来移动模式串的位置,避免不必要的比较。 而字符串哈希算法是一种将字符串映射为一个较短的固定长度的数值的算法。通过对字符串的每个字符进行一系列运算,如求幂、取模等,最终得到一个哈希值。这个哈希值可以代表该字符串的特征,不同字符串哈希值一般不会相同。 字符串哈希算法的主要作用是将字符串转化为一个定长的数字,方便在数据结构中进行比较和存储。在字符串匹配中,使用哈希算法可以将目标串和模式串转换为哈希值,然后比较哈希值是否相等来判断是否匹配。由于比较哈希值的时间复杂度较低,使用字符串哈希算法可以提高匹配效率。 总的来说,字符串匹配算法字符串哈希算法都是用来处理字符串匹配的问。KMP算法通过利用已知信息来减少比较次数,提高匹配效率;而字符串哈希算法则是将字符串转化为哈希值,便于进行比较和存储。两者都在一定程度上提高了字符串匹配的效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值