001.判定字符是否唯一
《程序员面试金典 第6版》
001.判定字符是否唯一
实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
示例 1:
输入: s = “leetcode”
输出: false
示例 2:
输入: s = “abc”
输出: true
限制:
0 <= len(s) <= 100
如果你不使用额外的数据结构,会很加分。
import java.util.HashMap;
import java.util.Map;
public class Test001 {
//方法一:通过字符串indexOf方法判断
public boolean isUnique01(String astr) {
if(astr == null || "".equals(astr)){
return true;
}
for(int i = 0; i<astr.length();i++){
char a = astr.charAt(i);
if(astr.lastIndexOf(a) != i){
return false;
}
}
return true;
}
//方法二:通过HashMap方式
public boolean isUnique02(String astr) {
if(astr==null || "".equals(astr)){
return true;
}
Map<String,Integer> map = new HashMap<>();
for(int i = 0; i < astr.length(); i++){
String a = String.valueOf(astr.charAt(i));
if(map.containsKey(a)){
return false;
}else{
map.put(a,i);
}
}
return true;
}
//执行
public static void main(String[] args) {
Test001 test = new Test001();
String input = "abcdefghijklmn";
boolean output01 = test.isUnique01(input);
boolean output02 = test.isUnique02(input);
System.out.println(output01);
System.out.println(output02);
}
}
002.判定是否互为字符重排
《程序员面试金典 第6版》
002.判定是否互为字符重排
给定两个字符串 s1 和 s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
示例 1:
输入: s1 = “abc”, s2 = “bca”
输出: true
示例 2:
输入: s1 = “abc”, s2 = “bad”
输出: false
说明:
0 <= len(s1) <= 100
0 <= len(s2) <= 100
import java.util.*;
public class Test002 {
//方法一:转换成数组并使用sort进行重排
public boolean CheckPermutation01(String s1, String s2) {
if ((s1==null||"".equals(s1)) && (s2==null||"".equals(s2))){//同时为空
return true;
}else if ((s1==null||"".equals(s1)) || (s2==null||"".equals(s2))){//有一个为空
return false;
}else if (s1.length()!=s2.length()){//都不为空,但长度不相等
return false;
}else if (s1.equals(s2)) {//完全相同直接返回true
return true;
}
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
Arrays.sort(c1);
Arrays.sort(c2);
s1 = new String(c1);
s2 = new String(c2);
return s1.equals(s2);
}
//法二:map计数,map.getOrDefault的运用是重点
public boolean CheckPermutation02(String s1, String s2) {
if ((s1==null||"".equals(s1)) && (s2==null||"".equals(s2))){//同时为空
return true;
}else if ((s1==null||"".equals(s1)) || (s2==null||"".equals(s2))){//有一个为空
return false;
}else if (s1.length()!=s2.length()){//都不为空,但长度不相等
return false;
}else if (s1.equals(s2)) {//完全相同直接返回true
return true;
}
Map<Character,Integer> mapS1 = getMap(s1);
Map<Character,Integer> mapS2 = getMap(s2);
char[] chars = s1.toCharArray();
for (char c : chars){
if (!mapS2.containsKey(c) || mapS1.get(c) != mapS2.get(c)){
return false;
}
}
return true;
}
public Map<Character,Integer> getMap(String s){
HashMap<Character, Integer> map = new HashMap<>();
char[] chars = s.toCharArray();
for(char c : chars){
map.put(c,map.getOrDefault(c,0)+1);
}
return map;
}
//方法三:筒计数,和上面的map计数类似 ,但是容器采用的是数组,更高效.因为char是基础类型所以方便很多
public boolean CheckPermutation03(String s1, String s2) {
if ((s1==null||"".equals(s1)) && (s2==null||"".equals(s2))){//同时为空
return true;
}else if ((s1==null||"".equals(s1)) || (s2==null||"".equals(s2))){//有一个为空
return false;
}else if (s1.length()!=s2.length()){//都不为空,但长度不相等
return false;
}else if (s1.equals(s2)) {//完全相同直接返回true
return true;
}
int[] ints1 = countArr(s1);
int[] ints2 = countArr(s2);
for (int i = 0; i < ints1.length; i++){
if (ints1[i] != ints2[i]){
return false;
}
}
return true;
}
public int[] countArr(String s){
int[] ints = new int[26];
char[] chars = s.toCharArray();
for(char c : chars){
ints[c-'a'] ++;//对下标所在值+1操作
}
return ints;
}
//执行
public static void main(String[] args) {
Test002 test = new Test002();
long timeStamp1 = System.currentTimeMillis();
boolean flag1 = test.CheckPermutation01("abcd","acbd");
long timeStamp2 = System.currentTimeMillis();
System.out.println("方法一[执行结果:"+flag1+",执行时间:"+ (timeStamp2-timeStamp1)+"ms]");
timeStamp1 = System.currentTimeMillis();
boolean flag2 = test.CheckPermutation02("abcd","acbd");
timeStamp2 = System.currentTimeMillis();
System.out.println("方法二[执行结果:"+flag2+",执行时间:"+ (timeStamp2-timeStamp1)+"ms]");
timeStamp1 = System.currentTimeMillis();
boolean flag3 = test.CheckPermutation02("abcd","acbd");
timeStamp2 = System.currentTimeMillis();
System.out.println("方法三[执行结果:"+flag3+",执行时间:"+ (timeStamp2-timeStamp1)+"ms]");
}
}
003.URL化
《程序员面试金典 第6版》
003.URL化
URL化。编写一种方法,将字符串中的空格全部替换为%20。
假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。
(注:用Java实现的话,请使用字符数组实现,以便直接在数组上操作。)
public class Test003 {
//方法1:最快的解法但是不符合题意
public String replaceSpaces(String S, int length) {
S = S.substring(0,length).replaceAll(" ","%20");
return S;
}
//方法2:使用字符数组的方法
public String replaceSpaces02(String S, int length) {
if ("".equals(S)||null==S||0==length){
return "";
}
char[] chars = S.toCharArray();
char[] charResult = new char[3*length];//按照最大的来,以防不够
int index = 0;//新字符数组的元素下标
for (int i = 0 ; i < length; i++){
if (' ' == chars[i]){//如果为空
charResult[index++] = '%';
charResult[index++] = '2';
charResult[index++] = '0';
}else{//不为空
charResult[index++] = chars[i];
}
}
return new String(charResult,0,index);
}
public static void main(String[] args) {
Test003 test = new Test003();
String s = test.replaceSpaces02("a b c ",6);
System.out.println(s);
}
}
004.判断回文排列
《程序员面试金典 第6版》
004.判断回文排列
给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。
回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。
回文串不一定是字典当中的单词。
示例1:
输入:“tactcoa”
输出:true(排列有"tacocat"、“atcocta”,等等)
public class Test004 {
/*
思路:
根据题意,需要判断给定字符串能否组成回文串
回文串是正读反读都一样的字符串
当字符数目为奇数时,那么单个字符的数量只能为1,其他必须是成对出现 比如aabbc,aaabb都可以组成回文串,其中aabbc中的c和aaabb中的a就属于单个未成对字符
当字符数目为偶数时,不能出现单个未成对字符,每个字符都必须时偶数
所以遍历字符数组,使用map计数的方法记录每个字符的数目,然后计算单个未成对字符的数量
最后再分奇数和偶数两种情况去判断就可以了
*/
public boolean canPermutePalindrome(String s) {
char[] chars = s.toCharArray();
Map<Character,Integer> countMap = new HashMap<>();
int singleNum = 0;//落单的字符个数
for (char c : chars){//遍历字符数组统计每个字符出现的数量
int count = (int)countMap.getOrDefault(c,0);
countMap.put(c,++count);
}
for (Integer val : countMap.values()){//遍历计数map获得每个字符的总个数
if (val%2!=0){//为奇数,则一定有一个字符是落单的
singleNum ++;
}
}
//偶数个字符的话,要求落单的字符数为0才是回文。奇数个字符的话,要求落单的字符数为1才是回文
if ((s.length()%2==0 && singleNum == 0) || (s.length()%2 !=0 && singleNum == 1)){
return true;
}
return false;
}
//优化版,去除了char[], 数组比较占内存
public boolean canPermutePalindrome02(String s) {
Map<Character,Integer> countMap = new HashMap<>();
int singleNum = 0;//落单的字符个数
for (int i = 0; i < s.length(); i++){//遍历字符数组统计每个字符出现的数量
countMap.put(s.charAt(i),countMap.getOrDefault(s.charAt(i),0)+1);
}
for (Integer val : countMap.values()){//遍历计数map获得每个字符的总个数
if (val%2!=0){//为奇数,则一定有一个字符是落单的
singleNum ++;
}
}
//偶数个字符的话,要求落单的字符数为0才是回文。奇数个字符的话,要求落单的字符数为1才是回文
if ((s.length()%2==0 && singleNum == 0) || (s.length()%2 !=0 && singleNum == 1)){
return true;
}
return false;
}
}