算法字符串模块判断字符串是否都只出现过一次

Posted 元空间

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法字符串模块判断字符串是否都只出现过一次相关的知识,希望对你有一定的参考价值。

目录

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
给定一个字符串str,如果str中的字符都只出现过一次,返回true,否则返回false
进阶问题
在空间复杂度为O(1)的前提下,尽量降低空间复杂度

解决方案

原问题
1、申请一个boolean类型的位数组,长度为255,如果字符串中的字符出现的种类超过255可以继续增加
2、遍历字符串,判断每一个字符的编码值是否在boolean数组中已经标记过,标记过的地方为true,如果标记过,则返回false。
进阶问题
1、使用非递归的方式对数组进行堆排序
2、遍历数组,判断是否存在相邻元素相等的情况,如果存在直接返回false。

代码编写

java语言版本

原问题:
常规bit位数组解法

    /**
     * 二轮测试方法一:判断字符是否只出现过一次
     * 空间O(N) 时间 O(n)
     * @param chars
     * @return
     */
    public static boolean isUniqueCp1(char[] chars) 
        if (chars == null || chars.length == 0) 
            return false;
        
        boolean[] map = new boolean[256];
        for (int i = 0; i < chars.length; i++) 
            if (map[chars[i]]) 
                return false;
            else 
                map[chars[i]] = true;
            
        
        return true;
    

堆排序节省空间解法

   /**
     * 空间O(1), 时间O(nlogn)
     * @param chars
     * @return
     */
    public static boolean isUniqueCp2(Character[] chars) 
        if (chars == null || chars.length == 0) 
            return false;
        
        heapSortCp1(chars);
        char pre = chars[0];
        for (int i = 1; i < chars.length; i++) 
            if (pre == chars[i]) 
                return false;
            else
                pre = chars[i];
            
        
        return true;
    

    /**
     * 非递归方式的堆排序
     * @param chars
     */
    private static void heapSortCp1(Character[] chars) 
        if (chars == null || chars.length == 0) 
            return;
        
        int len = chars.length;
        for (int i =  len/2+1; i >= 0; i--) 
            heapfiy(chars, i, len);
        
        for (int i = chars.length-1; i >= 0; i--) 
            CommonUtils.swapPlus(chars, 0, i);
            heapfiy(chars, 0, i);
        
    


    /**
     * 堆排序核心过程,这里排从小到大,大的下沉
     * @param chars
     * @param index
     * @Param charLen 这个变量表示当前chars的虚拟长度,超过的不参与排序
     */
    private static void heapfiy(Character[] chars, int index, int charLen) 
        int len = charLen;
        int parent = index;
        int left = parent*2+1;
        while (left < len) 
            int right = left + 1;
            int min = chars[left] < chars[parent] ? left : parent;
            if (right < len && chars[right] < chars[min]) 
                min = right;
            
            if (min != parent) 
                // 交换
                CommonUtils.swapPlus(chars, parent, min);
            else 
                // 直接出去
                break;
            
            // 下一轮准备
            parent = min;
            left = parent*2+1;
        
    

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

这道题如果是仅仅处理常规的业务逻辑,其实并没有什么太大的难度和意义。而对于大数据的情况下,内存不足以放下如此多的元素时,位数组的解法可以作为一种参考。堆排序其实用来做查重问题很少见,如果用来求大数据的top5类型的问题,堆排序绝对是优先考虑的算法,因为堆排序的时间复杂度在nlogn,类似于树形结构的特点,加上堆排序的交换特点可以快速的计算出top5的元素。后面会详细讲到。

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!

以上是关于算法字符串模块判断字符串是否都只出现过一次的主要内容,如果未能解决你的问题,请参考以下文章

字符串的遍历

KMP算法

前端与算法 leetcode 242. 有效的字母异位词

初级算法15. 有效的字母异位词

1.12 判断字符串第一次出现的位子 和 字符串是否存在

编程之法:面试和算法心得(最长回文子串)