声明:所有题目均来自LeetCode和牛客网
先立个flag,努力拿到offer之前,每日至少一题。
此文置顶,从现在开始。
文章目录
面试题03. 数组中重复的数字
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
思路:使用集合对数组进行去重,将数组中的元素遍历存入集合中,因为集合中元素只能存在一次,当遇到重复元素时无法添加进集合,此时就可以将重复的元素直接返回。
import java.util.TreeSet;
class Solution {
public int findRepeatNumber(int[] nums) {
TreeSet<Integer> set = new TreeSet<>();
for (int n : nums) {
if (!set.add(n)) {
return n;
}
}
return 0;
}
}
面试题 01.01. 判定字符是否唯一
实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
示例 1:
输入: s = “leetcode”
输出: false
示例 2:
输入: s = “abc”
输出: true
限制:
0 <= len(s) <= 100
如果你不使用额外的数据结构,会很加分。
题解:考虑数据结构的情况下,优先会想到使用集合,因为集合的特性可以高效去重。在限制的前提下使用String类中indexOf()与lastIndexOf()方法
来解决。
indexOf()返回指定字符在字符串中第一次出现处的索引
,如果没有则返回 -1。而lastIndexOf()方法则是返回最后一次出现的位置
。
因此使用for循环将字符串进行遍历,取出每一个字符使用indexOf()与lastIndexOf()方法对比他们的返回值,如果重复出现,则不相等。如果字符只出现一次,则相等。
class Solution {
public boolean isUnique(String astr) {
for (int i = 0; i < astr.length(); i++) {
if (astr.indexOf(astr.charAt(i)) != astr.lastIndexOf(astr.charAt(i)))
return false;
}
return true;
}
}
上述是一种比较直观的写法,我更倾向使用toCharArray()方法将字符串转换为字符数组
,让语句更加简洁。
class Solution {
public boolean isUnique(String astr) {
for (char ch : astr.toCharArray()) {
if (astr.indexOf(ch) != astr.lastIndexOf(ch))
return false;
}
return true;
}
}
面试题 01.02. 判定是否互为字符重排
给定两个字符串 s1 和 s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
示例 1:
输入: s1 = “abc”, s2 = “bca”
输出: true
示例 2:
输入: s1 = “abc”, s2 = “bad”
输出: false
说明:
0 <= len(s1) <= 100
0 <= len(s2) <= 100
题解:算是非常简单一道题了,第一次考虑的不够仔细,根据例子只想到s2重排可以变成s1。执行通过但是提交之后,测试用例“a”“ab”并未通过。所以这个重排两个字符串是相互的,也就是说这两个字符串含有同样的字符,只是字符顺序不同罢了。只需要对字符串进行排序对比,相同为true,不同为false。关于字符串排序,使用toCharArray()
方法将字符串转换成数组,通过Arrays.sort()
方法进行排序,之后使用equals
对比两个字符串的内容是否完全一致。
import java.util.Arrays;
class Solution {
public boolean CheckPermutation(String s1, String s2) {
char[] c1 = s1.toCharArray();
Arrays.sort(c1);
char[] c2 = s2.toCharArray();
Arrays.sort(c2);
return String.valueOf(c1).equals(String.valueOf(c2));
}
}
面试题 01.03. URL化
URL化。编写一种方法,将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。(注:用Java实现的话,请使用字符数组实现,以便直接在数组上操作。)
示例1:
输入:“Mr John Smith “, 13
输出:“Mr%20John%20Smith”
示例2:
输入:” “, 5
输出:”%20%20%20%20%20”
题解:这道题是使用java写的,按照题目要求需要使用字符数组。首先将已知字符串转换成字符数组c
,对这个数组进行遍历。因为真实长度是已知的,所以遍历的时候只需要遍历到已知长度length即可。创建一个新的字符数组c2,c2的长度最坏的情况需要考虑字符串全部是空格
,全部替换%20,就需要是原始字符串的三倍长度
。遍历字符数组c时把%20
看成是%
,2
,0
三个字符,当c中遇到空格时,将它们逐次添加进c2。最终返回c2字符串即可。
class Solution {
public String replaceSpaces(String S, int length) {
int count = 0;
char[] c = S.toCharArray();
char[] c2 = new char[length * 3];
for (int i = 0; i < length; i++) {
if (c[i] == ' ') {
c2[count++] = '%';
c2[count++] = '2';
c2[count++] = '0';
} else {
c2[count++] = c[i];
}
}
return new String(c2, 0, count);
}
}
面试题 01.04. 回文排列
给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。
回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。
回文串不一定是字典当中的单词。
示例1:
输入:“tactcoa”
输出:true(排列有"tacocat"、“atcocta”,等等)
题解:根据题意,回文字符串一定满足当字符串中字符个数为奇数时,一定只有一个字符是唯一的,字符个数为偶数时,字符至少是两两配对的
。按照这样的思想,可以使用集合去重。遍历字符串,将字符逐个添加进集合中,如果已经存在,就删除其中相应存在的字符
。即使有四个一样的字符,也会重复添加删除添加删除的操作,直到集合中不存在这个字符。当遍历结束后,集合中剩下的都是只出现一次的字符,如果是满足回文排序,那么集合中一定只有1个或0个元素
。此时只需要返回集合的大小<=1就可以了。
import java.util.Arrays;
class Solution {
public boolean canPermutePalindrome(String s) {
TreeSet<Character> set = new TreeSet<>();
for (char ch : s.toCharArray()) {
if (!set.add(ch))
set.remove(ch);
}
return set.size() <= 1;
}
}
A-凯撒密码
牛牛截获了一段由凯撒密码加密过的密文,凯撒密码指的是将字符偏移一定的单位,例如若偏移量为2,则a替换为c,b替换为d,c替换为e,…,z替换为b。若加密nowcoder,则密文为pqyeqfgt。现在牛牛发现对方加密包括数字、大写字母、小写字母,即0-9、A-Z、a-z的排列顺序进行偏移,现在牛牛截获了对方的一段密文以及偏移量,你能帮助牛牛破解密文吗。即给定一段密文str和偏移量d,求对应的明文。
输入 “pqyeqfgt”,2
输出 “nowcoder”
示例2
输入"123ABCabc",3
输出"yz0789XYZ"
题解:根据题意将,0-9、A-Z、a-z的排列字符存放进一个字符数组中,为了方便获取下标,把char数组转存进ArrayList数组al中
,将目标字符串遍历,使用al.indexOf()获取字符串中字符在数组中的下标,对小标进行偏移计算,当前下标减去偏移量小于0的时候,要为它加上数组长度
得到最终的下标,获取字符进行字符串拼接返回。
import java.util.ArrayList;
public class Solution {
/**
* 解密密文
*
* @param str string字符串 密文
* @param d int整型 偏移量
* @return string字符串
*/
public String decode(String str, int d) {
StringBuilder res = new StringBuilder();
ArrayList al = new ArrayList();
char[] arr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z'};
for (char n : arr)
al.add(n);
for (int i = 0; i < str.length(); i++) {
int index = al.indexOf(str.charAt(i));
if (index - d < 0) {
index += al.size();
}
res.append(al.get(index - d));
}
return res.toString();
}
}
27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:
给定 nums = [3,2,2,3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
你不需要考虑数组中超出新长度后面的元素。
题解: 将数组遍历,每一个不等于val的元素从数组的0位置开始赋值
,使用count来记录位置,直到遍历完所有元素,前count位都是不为val的元素
,根据题意只需要返回count长度。
class Solution {
public int removeElement(int[] nums, int val) {
int count = 0;
for(int n: nums){
if(n!=val){
nums[count++] = n;
}
}
return count;
}
}