[程序员代码面试指南]判断字符数组中是否所有字符只出现一次(堆排序)

题意

如题,并要求额外空间复杂度为O(1)。

题解

  • 若不要求额外空间复杂度。普通做法时间复杂度O(n).
  • 此题思路是先排序,然后判断相邻两个是否有重复元素。时间复杂度O(n),空间复杂度O(1).

堆排序再理解

堆排序步骤
1、堆的初始化,从最后一个非叶节点为根调整,向前一个个节点为根调整。
2、从最后一个元素开始分别和堆顶元素swap,始终以树的第一个位置的节点为根调整。

代码

package Character;

import java.util.Scanner;

public class OccurOnece {
	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		String str=in.next();
		boolean ans=isUnique(str.toCharArray());
		if(ans) {
			System.out.print("Unique.");
		}
		else {
			System.out.print("Not unique.");
		}
	}
	
	public static boolean isUnique(char[] str) {
		if(str==null) {
			return true;
		}
		heapSort(str);
		for(int i=0;i<str.length-1;++i) {
			if(str[i]==str[i+1]) {
				return false;
			}
		}
		return true;
	}
	
	public static void heapSort(char[] str) {//堆排序
		buildHeap(str);//建堆 heapify一波
		
		for(int i=str.length-1;i>=0;--i) {//排序 swap、heapify一波
			swap(str,0,i);
			heapify(str,0,i-1);
		}
	}
	
	public static void buildHeap(char[] str) {
		for(int i=str.length/2-1;i>=0;--i) {
			heapify(str,i,str.length-1);
		}
	}
	
	public static void heapify(char[] str,int idx,int heapSize) {
		int lIdx=idx*2+1;
		int rIdx=idx*2+2;
		int maxIdx=idx;
		while(lIdx<=heapSize) {
			if(str[lIdx]>str[idx]) {
				maxIdx=lIdx;
			}
			if(rIdx<=heapSize&&str[rIdx]>str[idx]) {
				maxIdx=rIdx;
			}
			
			if(maxIdx!=idx) {
				swap(str,idx,maxIdx);
				idx=maxIdx;
				lIdx=idx*2+1;
				rIdx=idx*2+2;
			}
			else break;//到当前节点是以它为根节点的数的最大值停止
		}
	}
	
	public static void swap(char[] str,int idx1,int idx2) {
		char tmp=str[idx1];
		str[idx1]=str[idx2];
		str[idx2]=tmp;
	}
}
原文地址:https://www.cnblogs.com/coding-gaga/p/11048486.html