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

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

问题

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

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

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

分析

如果只是基础问题,那么直接使用数组或者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"));
    }
}


相关文章
|
3月前
|
算法 Python
数据结构算法--4堆排序
堆排序过程概述:建立大根堆,将堆顶最大元素移出并替换为末尾元素,调整保持堆性质,重复此过程直至堆为空,实现排序。时间复杂度为O(nlogn)。Python中可用heapq模块进行堆操作。
|
1月前
|
算法
【算法】位运算算法——判断字符是否唯一
【算法】位运算算法——判断字符是否唯一
|
1月前
|
算法
【算法】滑动窗口——找到字符串中所有字母异位词
【算法】滑动窗口——找到字符串中所有字母异位词
|
1月前
|
算法
【算法】滑动窗口——无重复字符的最长子串
【算法】滑动窗口——无重复字符的最长子串
|
3月前
|
存储 算法 程序员
数据结构与算法===递归
数据结构与算法===递归
|
1月前
|
算法 Java
掌握算法学习之字符串经典用法
文章总结了字符串在算法领域的经典用法,特别是通过双指针法来实现字符串的反转操作,并提供了LeetCode上相关题目的Java代码实现,强调了掌握这些技巧对于提升算法思维的重要性。
|
1月前
|
算法
【算法】递归、搜索与回溯——汉诺塔
【算法】递归、搜索与回溯——汉诺塔
|
2月前
|
自然语言处理 算法 搜索推荐
字符串相似度算法完全指南:编辑、令牌与序列三类算法的全面解析与深入分析
在自然语言处理领域,人们经常需要比较字符串,这些字符串可能是单词、句子、段落甚至是整个文档。如何快速判断两个单词或句子是否相似,或者相似度是好还是差。这类似于我们使用手机打错一个词,但手机会建议正确的词来修正它,那么这种如何判断字符串相似度呢?本文将详细介绍这个问题。
234 1
|
2月前
|
数据采集 算法 JavaScript
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
JavaScript字符串搜索涵盖`indexOf`、`includes`及KMP算法。`indexOf`返回子字符串位置,`includes`检查是否包含子字符串。KMP是高效的搜索算法,尤其适合长模式匹配。示例展示了如何在数据采集(如网页爬虫)中使用这些方法,结合代理IP进行安全搜索。代码示例中,搜索百度新闻结果并检测是否含有特定字符串。学习这些技术能提升编程效率和性能。
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
|
1月前
|
算法
【算法】递归总结:循环与递归的区别?递归与深搜的关系?
【算法】递归总结:循环与递归的区别?递归与深搜的关系?