第一题 Strings Homomorphism
Given two strings s and t, determine if they are isomorphic.
Two strings are isomorphic if the characters in s can be replaced to get t.
All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.
注意事项
You may assume both s and t have the same length.
样例
Given s = "egg", t = "add", return true.
Given s = "foo", t = "bar", return false.
Given s = "paper", t = "title", return true.
注: 将字母作为键,判断是否重复。
public boolean isIsomorphic(String s, String t) {
int[] flag1 = new int[s.length()];
int[] flag2 = new int[t.length()];
if(flag1.length != flag2.length){
return false;
}
HashMap<Character, Integer> map1 = new HashMap<>();
HashMap<Character, Integer> map2 = new HashMap<>();
int tmp = 0;
for(int i = 0 ; i < s.length(); i ++){
if(!map1.containsKey(s.charAt(i))){
map1.put(s.charAt(i), tmp);
tmp++;
flag1[i] = tmp;
}else{
flag1[i] = map1.get(s.charAt(i));
}
}
tmp = 0 ;
for(int i = 0 ; i < t.length(); i ++){
if(!map2.containsKey(t.charAt(i))){
map2.put(t.charAt(i), tmp);
tmp++;
flag2[i] = tmp;
}else{
flag2[i] = map2.get(t.charAt(i));
}
if(flag1[i] != flag2[i]){
return false;
}
}
return true;
}
第二题 First Position Unique Character
Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1.
样例
Given s = "lintcode", return 0.
Given s = "lovelintcode", return 2.
public int firstUniqChar(String s) {
if(s == null || s.length() == 0){
return -1;
}
for(int i = 0; i<s.length() - 1; i++){
char p = s.charAt(i);
if(s.indexOf(p , i + 1) < 0 && s.indexOf(p) == i){
return i;
}
}
if(s.indexOf(s.charAt(s.length() - 1)) == s.length() - 1){
return s.length() - 1;
}
return -1;
}
第三题 各位相加
给出一个非负整数 num,反复的将所有位上的数字相加,直到得到一个一位的整数。
样例
给出 num = 38。
相加的过程如下:3 + 8 = 11,1 + 1 = 2。因为 2 只剩下一个数字,所以返回2。
public int addDigits(int num) {
if(num < 10){
return num;
}
int[] number = new int[20];
int i = 0;
int sum = 0;
while(num > 0){
number[i] = num % 10;
i++;
num = num / 10;
}
for(int j = 0 ; j < i ; j ++){
sum += number[j];
}
if(sum >= 10){
return addDigits(sum);
}else{
return sum;
}
}
你可以不用任何的循环或者递归算法,在 O(1) 的时间内解决这个问题么?
public static int addDigits(int num) {
String numStr = Integer.toString(num);
while(numStr.length() > 1) {
int sum = 0;
for(int i = 0; i < numStr.length(); i++) {
sum = sum + Character.getNumericValue(numStr.charAt(i));
System.out.println(Character.getNumericValue(numStr.charAt(i)));
}
numStr = Integer.toString(sum);
}
return Integer.parseInt(numStr);
}
第四题 移动零
题目
给一个数组 nums 写一个函数将0
移动到数组的最后面,非零元素保持原数组的顺序
注意事项
1.必须在原数组上操作
2.最小化操作数
样例给出 nums =[0, 1, 0, 3, 12], 调用函数之后, nums =[1, 3, 12, 0, 0]
分析
这类数组原地删除数据的题目,考察的就是两根指针的应用,注意掌握两根指针的思想,这一类问题就可以迎刃而解了。
我们设置两根指针slow和fast,fast每次都递增,所以称之为fast,当遍历到不是0的时候,slow指针就存储fast此时遍历的元素,slow加一,当遍历到需要删除的元素0(就相当于移动0到最后)时,略过slow,直接fast++,相当于删除了0.同时设置一个变量记录新数组的长度。
最后我们再遍历剩下的元素,并给他们赋值为0即可。
这道题可以看作是删除元素那道题的扩展应用
#代码
public void moveZeroes(int[] nums) {
int show = 0;
for(int i = 0 ; i < nums.length; i ++){
if(nums[i] != 0 ){
nums[show] = nums[i];
show++;
}
}
for(int i = show; i < nums.length; i ++){
nums[i] = 0;
}
}
第五题 玩具工厂
工厂模式是一种常见的设计模式。请实现一个玩具工厂 ToyFactory 用来产生不同的玩具类。可以假设只有猫和狗两种玩具。
样例
ToyFactory tf = ToyFactory(); Toy toy = tf.getToy('Dog'); toy.talk(); >> Wow toy = tf.getToy('Cat'); toy.talk(); >> Meow
interface Toy {
void talk();
}
class Dog implements Toy {
public void talk(){
System.out.println("Wow");
}
}
class Cat implements Toy {
public void talk(){
System.out.println("Meow");
}
}
public class ToyFactory {
Dog dog = new Dog();
Cat cat = new Cat();
public Toy getToy(String type) {
if(type.equals("Dog")){
return dog;
}
if(type.equals("Cat")){
return cat;
}
return null;
}
}
第六题 左填充
实现一个leftpad库,如果不知道什么是leftpad可以看样例
样例
leftpad("foo", 5) >> " foo" leftpad("foobar", 6) >> "foobar" leftpad("1", 2, "0") >> "01"
public class StringUtils {
static public String leftPad(String originalStr, int size) {
if (originalStr.length() >= size){
return originalStr;
}
StringBuffer sbr = new StringBuffer();
if(originalStr.length() < size){
for(int i = originalStr.length(); i < size; i ++){
sbr.append(" ");
}
sbr.append(originalStr);
}
return sbr.toString();
}
static public String leftPad(String originalStr, int size, char padChar) {
StringBuffer sbNew = new StringBuffer();
if (originalStr.length() >= size){
return originalStr;
}
if(originalStr.length() < size){
for(int i = originalStr.length(); i < size; i ++){
sbNew.append(padChar);
}
sbNew.append(originalStr);
}
return sbNew.toString();
}
}
第七题 丑数
写一个程序来检测一个整数是不是丑数。
丑数的定义是,只包含质因子 2, 3, 5 的正整数。比如 6, 8 就是丑数,但是 14 不是丑数以为他包含了质因子 7。
注意事项
可以认为 1 是一个特殊的丑数。
样例
给出 num = 8,返回 true。
给出 num = 14,返回 false。
public boolean isUgly(int num) {
if(num == 1){
return true;
}
if(num <= 0){
return false;
}
while(num >= 2 ){
if(num % 2 == 0){
num = num / 2;
continue;
}else if(num % 3 == 0){
num = num / 3;
continue;
}else if(num % 5 == 0){
num = num / 5;
continue;
}else{
return false;
}
}
return true;
}
第八题 栅栏染色
我们有一个栅栏,它有n个柱子,现在要给柱子染色,有k种颜色可以染。
必须保证任意两个相邻的柱子颜色不同,求有多少种染色方案。
注意事项
n和k都是非负整数
样例
n = 3, k = 2, return 6
post 1, post 2, post 3 way1 0 0 1 way2 0 1 0 way3 0 1 1 way4 1 0 0 way5 1 0 1 way6 1 1 0
问题描述
lintcode表述有问题,原文是“必须保证任意两个相邻的柱子颜色不同,应该表述为“不能有连续三个柱子颜色相同”。
参考
参考里改掉的表述感觉也不对,还是应该说“不能有连续三个柱子颜色相同”。
笔记
在改掉问题表述的情况下:
假设buff[i]为有i个柱子时的染色方案。可以分为两种情况:
1. 最后两个柱子颜色相同。
前i-2个柱子已经有buff[i-2]种方案了,第i-1个和第i个柱子取相同的颜色,但是要和i-2个柱子不同,有(k-1)种取法。
2. 最后两个柱子颜色不同。
前i-1个柱子符合要求,已经有buff[i-1]种方案了,第i个柱子的颜色要和第i-1个柱子颜色不同,还有(k-1)种方案。
由此,状态转移方程为:
buff[i] = buff[i-1] * (k-1) + buff[i-2] * (k-1);
初始条件:
buff[1] = k; buff[2] = k*k;
public int numWays(int n, int k) {
if (n == 0) {
return 0;
}
if (n == 1) {
return k;
}
if (n == 2) {
return k * k;
}
int pre = k;
int now = k * k;
for (int i = 3; i <= n; i++) {
int tmp = now;
now = (pre + now) * (k - 1);
pre = tmp;
}
return now;
}
第九题 单词计数
使用 map reduce 来计算单词频率
https://hadoop.apache.org/docs/r1.2.1/mapred_tutorial.html#Example%3A+WordCount+v1.0
样例
chunk1: "Google Bye GoodBye Hadoop code" chunk2: "lintcode code Bye" Get MapReduce result: Bye: 2 GoodBye: 1 Google: 1 Hadoop: 1 code: 2 lintcode: 1
/**
* Definition of OutputCollector:
* class OutputCollector<K, V> {
* public void collect(K key, V value);
* // Adds a key/value pair to the output buffer
* }
*/
public class WordCount {
public static class Map {
public void map(String key, String value, OutputCollector<String, Integer> output) {
String[] tmp = value.split(" ");
for(int i = 0;i < tmp.length;i++){
output.collect(tmp[i],1);
}
}
}
public static class Reduce {
public void reduce(String key, Iterator<Integer> values,
OutputCollector<String, Integer> output) {
int count = 0;
while(values.hasNext()){
count += values.next();
}
output.collect(key , count);
}
}
}
第十题 快乐数
写一个算法来判断一个数是不是"快乐数"。
一个数是不是快乐是这么定义的:对于一个正整数,每一次将该数替换为他每个位置上的数字的平方和,然后重复这个过程直到这个数变为1,或是无限循环但始终变不到1。如果可以变为1,那么这个数就是快乐数。
样例
19 就是一个快乐数。
1^2 + 9^2 = 82 8^2 + 2^2 = 68 6^2 + 8^2 = 100 1^2 + 0^2 + 0^2 = 1
private static int COUNT = 0;
public boolean isHappy(int n) {
if(n < 0 ){
return false;
}
if(n == 1){
return true;
}
int[] number = new int[10];
int i = 0;
while ( n > 0){
number[i] = n % 10;
n = n / 10;
i++;
}
int sum = 0 ;
for(i = 0 ; i < number.length; i++){
sum += (number[i] * number[i]);
}
if(sum == 1){
return true;
}else{
COUNT = COUNT + 1;
if(COUNT > 20){
return false;
}else{
return isHappy(sum);
}
}
}