前言
如果想进大厂工作,除了基础知识,项目经验,还有一些非常重要的能力需要锻炼,其中最重要的就是算法。算法题千千万,但是类型也就几十种,接下来的系列文章,我将面试中常见的算法题类型进行归纳。
数组面试题01. 判定字符是否唯一
实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
示例 1:
输入: s = "leetcode"
输出: false
示例 2:
输入: s = "abc"
输出: true
限制:
0 <= len(s) <= 100
如果你不使用额外的数据结构,会很加分。
代码:
(1)第一种解法
class Solution {
public boolean isUnique(String astr) {
String [] arr = astr.split("");
int count = 0;
for (int i = 0; i < arr.length; i++) {
count = 0;
for (int j = 0; j < arr.length; j++) {
// 这里有一个小细节,就是比较两个字符是否相等用==,还是equals()
// ==对于基本数据类型,比较的是它们的值;对于复合数据类型(类、接口、数组),比较的是他们在内存中的存放地址
// equals方法比较的是字符串的内容是否相同
// 答案是使用equals()
if (arr[i].equals(arr[j])) {
count++;
}
if (count >= 2) {
return false;
}
}
}
return true;
}
}
(2)第二种解法 HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合
class Solution {
public boolean isUnique(String astr) {
HashSet<Character> hashSet = new HashSet<>();
for (int i = 0; i < astr.length(); i++) {
hashSet.add(astr.charAt(i));
}
return hashSet.size() == astr.length();
}
}
数组面试题02. 判定是否互为字符重排
实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
给定两个字符串 s1 和 s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
示例1:
输入: s1 = "abc", s2 = "bca"
输出: true
示例2:
输入: s1 = "abc", s2 = "bad"
输出: false
说明:
0 <= len(s1) <= 100
0 <= len(s2) <= 100
分析
若s1,s2字符串长度不相等,则「不互为重排」;
若 s1,s2某对应字符数量不同,则「不互为重排」;
否则,若s1,s2所有对应字符数量都相同,则「互为重排」;
(1)当s1,s2字符数量相同时,读取s1中的一个字符,然后遍历s2,如果与s1中的该字符相同,则把s2中的这个字符改为"0"
(2)遍历s1中的每一个字符,重复步骤(1)
(3)遍历s2中的"0",如果数量与s2长度相等,则s1,s2互为重排;否则,s1,s2不互为重排
代码
class Solution {
public boolean CheckPermutation(String s1, String s2) {
char[] arr1 = s1.toCharArray();
char[] arr2 = s2.toCharArray();
if (arr1.length != arr2.length) {
return false;
} else {
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr2.length; j++) {
if (arr1[i] == arr2[j]) {
arr2[j] = '0';
break;
}
}
}
int count = 0;
for (int j = 0; j < arr2.length; j++) {
if (arr2[j] == '0') {
count++;
}
}
if (count == arr2.length) {
return true;
} else {
return false;
}
}
}
}
数组面试题03. URL化
URL化。编写一种方法,将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。(注:用Java实现的话,请使用字符数组实现,以便直接在数组上操作。)
示例1:
输入:"Mr John Smith ", 13
输出:"Mr%20John%20Smith"
示例2:
输入:" ", 5
输出:"%20%20%20%20%20"
提示:
字符串长度在 [0, 500000] 范围内。
代码
class Solution {
public String replaceSpaces(String S, int length) {
StringBuilder stringBuilder = new StringBuilder();
// 逐渐遍历字符串
for (int i = 0; i < length; i++) {
// 如果不是空格就加入到StringBuilder中,如果是空格
// 就把"%20"加入到StringBuilder中
char ch = S.charAt(i);
if (ch == ' ') {
stringBuilder.append("%20");
} else {
stringBuilder.append(ch);
}
}
return stringBuilder.toString();
}
}
数组面试题04. 回文排列
给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。回文串不一定是字典当中的单词。
示例1:
输入:"tactcoa"
输出:true(排列有"tacocat"、"atcocta",等等)
分析:
根据字符串长度,「回文串」可分为两种情况:
「回文串」长度为偶数:所有不同字符的出现次数都为「偶数」;
「回文串」长度为奇数:位于中点的字符出现「奇数」次,其余字符出现「偶数」次;
因此,某字符串是回文串排列之一的「充要条件」为:此字符串中,最多只有一种字符的出现次数为「奇数」,其余所有字符的出现次数都为「偶数」。
考虑使用「哈希表」统计给定字符串中各字符的数量,再根据以上规则判断字符串是否为回文串排列之一。
代码:
class Solution {
public boolean canPermutePalindrome(String s) {
// 初始化哈希表
HashMap<Character, Integer> dic = new HashMap<>();
// 统计字符串中各字符的数量
for (int i = 0; i < s.length(); i++) {
dic.put(s.charAt(i), dic.getOrDefault(s.charAt(i), 0) + 1);
// getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。
// HashMap中key是不可以重复的,如果重复添加的话,HashMap会自动覆盖key一样的数据,保证一个key对应一个value
// 比如第一次读取到a,则key = a, value = 1;第二次也读取到a,则key = a, value = 2
}
int odd = 0;
for (int val : dic.values()) {
// 统计“数量为奇数”字符的个数
if (val % 2 == 1) {
// 若“数量为奇数”的字符个数 > 1 ,则不是回文串排列
if (++odd > 1) // 注意 ++odd > 1 是先执行 odd 自增,再执行逻辑判断; odd++ 的顺序反之
return false;
}
}
// 若“数量为奇数”的字符个数 <= 1 ,则是回文串排列
return true;
}
}