【算法】非递归堆排序判断字符串中所有字符是否只出现一次

简介: 【算法】非递归堆排序判断字符串中所有字符是否只出现一次

问题

给定一个字符串,判断当前字符串中是否所有的字符只出现一次。

是否能做到不使用额外空间的情况下,来完成此题?

这是我的一道面试的算法题,现在简单的给出一下思路以及答案。

分析

如果只是基础问题,那么直接使用数组或者hashmap就可以很快的解答这道题。

方法如下:

public static boolean isUniqueBasic(String str){
        if (str==null || str.equals("")){
            return false;
        }
        boolean [] chars = new boolean[256];
        for(int i=0;i<str.toCharArray().length;i++){
            if (chars[str.charAt(i)]){
                return false;
            }
            chars[str.charAt(i)]=true;
        }
        return true;
    }

这种方法的时间复杂度为O(N),额外空间复杂度也为O(N),当然,如果直接给这种答案,肯定是过不了面试的。

所以我考虑到可以用排序,用完排序之后,由于所有的字符有序了,那么只需要在判断一次当前字符是否和下一个字符相等即可得到答案。

比较快的排序算法,有归并,快排,桶,基数排序等。

归并结合手摇算法确实可以使得额外的空间复杂度为O(1),但是时间复杂度最差可能O(N2),所以不使用这种方法。

这里使用的是桶排序配合非递归的方式来实现O(1)的空间复杂度。

其实这里面试官估计考察的就是我对几种排序算法的理解了。

package com.base.learn.string;
import sun.misc.ObjectInputFilter;
/**
 * @author: 张锦标
 * @date: 2023/5/25 12:09
 * CharIsUnique类
 * 当前类用于判断字符串中的所有字符是否只出现一次
 * 并且保证了额外空间占用为O(1)
 * 使用的是非递归堆排序
 */
public class CharIsUnique {
    public static boolean isUniqueBasic(String str){
        if (str==null || str.equals("")){
            return false;
        }
        boolean [] chars = new boolean[256];
        for(int i=0;i<str.toCharArray().length;i++){
            if (chars[str.charAt(i)]){
                return false;
            }
            chars[str.charAt(i)]=true;
        }
        return true;
    }
    public static boolean isUnique(String str) {
        char[] chars = str.toCharArray();
        if (chars == null) {
            return true;
        }
        headSort(chars);
        for (int i = 1; i < chars.length; i++) {
            if (chars[i - 1] == chars[i]) {
                return false;
            }
        }
        return true;
    }
    public static void headSort(char[] chars) {
        for (int i = 0; i < chars.length; i++) {
            //构造大顶堆
            heapInsert(chars, i);
        }
        //开始使用堆排序
        for (int i = chars.length - 1; i > 0; i--) {
            swap(chars, 0, i);
            heapify(chars, 0, i);
        }
    }
    /**
     * 当前方法用于不断的构造一个大顶堆
     *
     * @param chars
     * @param i
     */
    private static void heapInsert(char[] chars, int i) {
        int parent = 0;
        while (i != 0) {
            parent = (i - 1) / 2;
            if (chars[parent] < chars[i]) {
                swap(chars, parent, i);
                i = parent;
            } else {
                break;
            }
        }
    }
    private static void heapify(char[] chars, int i, int size) {
        int left = i * 2 + 1;
        int right = i * 2 + 2;
        int largest = i;
        while (left < size) {
            if (chars[left] > chars[i]) {
                largest = left;
            }
            if (right < size && chars[right] > chars[largest]) {
                largest = right;
            }
            if (largest != i) {
                swap(chars, largest, i);
            } else {
                break;
            }
            i = largest;
            left = 2 * i + 1;
            right = 2 * i + 2;
        }
    }
    private static void swap(char[] chars, int i, int i1) {
        char temp = chars[i];
        chars[i] = chars[i1];
        chars[i1] = temp;
    }
    public static void main(String[] args) {
        System.out.println(isUnique("abcda"));
    }
}


相关文章
|
2月前
|
算法 前端开发 数据处理
小白学python-深入解析一位字符判定算法
小白学python-深入解析一位字符判定算法
52 0
|
4月前
|
算法
【算法】位运算算法——判断字符是否唯一
【算法】位运算算法——判断字符是否唯一
|
4月前
|
算法
【算法】滑动窗口——找到字符串中所有字母异位词
【算法】滑动窗口——找到字符串中所有字母异位词
|
4月前
|
算法
【算法】滑动窗口——无重复字符的最长子串
【算法】滑动窗口——无重复字符的最长子串
|
1月前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
48 2
|
2月前
|
算法
两个字符串匹配出最长公共子序列算法
本文介绍了最长公共子序列(LCS)问题的算法实现,通过动态规划方法求解两个字符串的最长公共子序列,并提供了具体的编程实现细节和示例。
97 1
两个字符串匹配出最长公共子序列算法
|
2月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
32 1
|
2月前
|
算法 搜索推荐
数据结构与算法学习十八:堆排序
这篇文章介绍了堆排序是一种通过构建堆数据结构来实现的高效排序算法,具有平均和最坏时间复杂度为O(nlogn)的特点。
75 0
数据结构与算法学习十八:堆排序
|
2月前
|
算法 搜索推荐
算法之堆排序
本文介绍了堆排序算法的原理和实现,通过构建最大堆或最小堆,利用堆的性质进行高效的排序,并提供了具体的编程实现细节和示例。
29 0
算法之堆排序
|
2月前
|
算法 Java Go
深入了解堆排序算法
深入了解堆排序算法
37 1