比较经典的题:61、63、64、65、66、67、68、69、70、72、73、76、79、80、82
61、无缓存交换
题目描述
请编写一个函数,函数内不使用任何临时变量,直接交换两个数的值。
给定一个int数组AB,其第零个元素和第一个元素为待交换的值,请返回交换后的数组。
测试样例:
[1,2]
返回:[2,1]
import java.util.*;
public class Exchange {
public int[] exchangeAB(int[] AB) {
// write code here
AB[0] ^= AB[1];
AB[1] ^= AB[0];
AB[0] ^= AB[1];
return AB;
//return new int[]{AB[1],AB[0]};
}
}
62、井字棋
题目描述
对于一个给定的井字棋棋盘,请设计一个高效算法判断当前玩家是否获胜。
给定一个二维数组board,代表当前棋盘,其中元素为1的代表是当前玩家的棋子,为0表示没有棋子,为-1代表是对方玩家的棋子。
测试样例:
[[1,0,1],[1,-1,-1],[1,-1,0]]
返回:true
import java.util.*;
public class Board {
public boolean checkWon(int[][] board) {
// write code here
if(board[0][0] + board[1][1] + board[2][2] == 3) return true;
if(board[2][0] + board[1][1] + board[0][2] == 3) return true;
for(int i=0;i<3;i++){
if(board[i][0] + board[i][1] + board[i][2] == 3) return true;
if(board[0][i] + board[1][i] + board[2][i] == 3) return true;
}
return false;
}
}
63、无判断max
题目描述
请编写一个方法,找出两个数字中最大的那个。条件是不得使用if-else等比较和判断运算符。
给定两个int a和b,请返回较大的一个数。若两数相同则返回任意一个。
测试样例:
1,2
返回:2
import java.util.*;
public class Max {
public int getMax(int a, int b) {
// write code here
return (int)((a+b)/2.0+Math.abs(a-b)/2.0);
}
}
64、珠玑妙算
题目描述
我们现在有四个槽,每个槽放一个球,颜色可能是红色®、黄色(Y)、绿色(G)或蓝色(B)。例如,可能的情况为RGGB(槽1为红色,槽2、3为绿色,槽4为蓝色),作为玩家,你需要试图猜出颜色的组合。比如,你可能猜YRGB。要是你猜对了某个槽的颜色,则算一次“猜中”。要是只是猜对了颜色但槽位猜错了,则算一次“伪猜中”。注意,“猜中”不能算入“伪猜中”。
给定两个string A和guess。分别表示颜色组合,和一个猜测。请返回一个int数组,第一个元素为猜中的次数,第二个元素为伪猜中的次数。
测试样例:
“RGBY”,“GGRR”
返回:[1,1]
import java.util.*;
public class Result {
public int[] calcResult(String secret, String guess) {
// write code here
int bulls = 0, cows = 0;
int len = secret.length();
HashMap<Character,Integer> hm = new HashMap();
for(int i=0; i<len ; i++){
if(secret.charAt(i) == guess.charAt(i)){
bulls++;
}
else hm.put(secret.charAt(i),hm.getOrDefault(secret.charAt(i), 0)+1);
}
for(int i=0;i<len;i++){
if(secret.charAt(i) != guess.charAt(i) &&
hm.getOrDefault(guess.charAt(i),0) != 0 ){
cows++;
hm.put(guess.charAt(i),hm.get(guess.charAt(i))-1);
}
}
return new int[]{bulls,cows};
}
}
65、阶乘尾0
题目描述
请设计一个算法,计算n的阶乘有多少个尾随零。
给定一个int n,请返回n的阶乘的尾零个数。保证n为正整数。
测试样例:
5
返回:1
import java.util.*;
public class Factor {
public int getFactorSuffixZero(int n) {
// write code here
int result = 0;
while(n > 0){
result += (n/=5);
}
return result;
}
}
66、最小调整有序
题目描述
有一个整数数组,请编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的。注意:n-m应该越小越好,也就是说,找出符合条件的最短序列。
给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的起点和终点。(原序列位置从0开始标号,若原序列有序,返回[0,0])。保证A中元素均为正整数。
测试样例:
[1,4,6,5,9,10],6
返回:[2,3]
import java.util.*;
public class Rearrange {
public int[] findSegment(int[] A, int n) {
// write code here
int left=0,right=0;
int curMax=A[0],curMin=A[n-1];
for(int i=1;i<n;i++){
curMax = Math.max(A[i],curMax);
if(A[i] < curMax){
right = i;
}
}
for(int i=n-1;i>=0;i--){
curMin = Math.min(A[i],curMin);
if(A[i] > curMin){
left = i;
}
}
return new int[]{left,right};
}
}
67、数字发音
题目描述
有一个非负整数,请编写一个算法,打印该整数的英文描述。
给定一个int x,请返回一个string,为该整数的英文描述。
测试样例:
1234
返回:“One Thousand,Two Hundred Thirty Four”
import java.util.*;
public class ToString {
private String[] belowTen = new String[]{"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
private String[] belowTwenty = new String[]{"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen",
"Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
private String[] belowHundred = new String[]{"", "Ten", "Twenty", "Thirty", "Forty",
"Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
public String toString(int x) {
// write code here
if (x == 0) return "Zero";
return helper(x);
}
private String helper(int num) {
String result = "";
if (num < 10) result = belowTen[num];
else if (num < 20) result = belowTwenty[num - 10];
else if (num < 100) result = belowHundred[num / 10] + " " + helper(num % 10);
else if (num < 1000) result = helper(num / 100) + " Hundred " + helper(num % 100);
else if (num < 1000000) result = helper(num / 1000) + " Thousand" +( num % 1000 > 0 ? "," : " ") + helper(num % 1000);
else if (num < 1000000000) result = helper(num / 1000000) + " Million" + (num % 1000000 > 0 ? "," : " ") + helper(num % 1000000);
else result = helper(num / 1000000000) + " Billion " + helper(num % 1000000000);
return result.trim();
}
}
68、最大连续子序列和
题目描述
对于一个有正有负的整数数组,请找出总和最大的连续数列。
给定一个int数组A和数组大小n,请返回最大的连续数列的和。保证n的大小小于等于3000。
测试样例:
[1,2,3,-6,1]
返回:6
import java.util.*;
public class MaxSum {
public int getMaxSum(int[] A, int n) {
// write code here
if(n == 0) return 0;
int maxSum=A[0], thisSum=0;
for(int i=0;i < n; i++){
thisSum += A[i];
if(thisSum > maxSum){
maxSum = thisSum;
}
if(thisSum < 0){
thisSum = 0;
}
}
return maxSum;
}
}
69、词频统计
题目描述
请设计一个高效的方法,找出任意指定单词在一篇文章中的出现频数。
给定一个string数组article和数组大小n及一个待统计单词word,请返回该单词在文章中的出现频数。保证文章的词数小于等于1000。
import java.util.*;
class TrieNode {
public char val;
public boolean isWord;
public int cnt;
public TrieNode[] children = new TrieNode[26];
public TrieNode() {}
TrieNode(char c){
this.val = c;
}
}
class Trie {
private TrieNode root;
/** Initialize your data structure here. */
public Trie() {
root = new TrieNode(' ');
}
/** Inserts a word into the trie. */
public void insert(String word) {
TrieNode ws = root;
for(int i=0 ; i < word.length() ; i++){
char c = word.charAt(i);
if(ws.children[c- 'a'] == null){
ws.children[c - 'a'] = new TrieNode(c);
}
ws = ws.children[c - 'a'];
}
ws.isWord = true;
ws.cnt++;
}
/** Returns if the word is in the trie. */
public int search(String word) {
TrieNode ws = root;
ws = helper(word,0,ws);
return (ws != null && ws.isWord) ? ws.cnt : 0;
}
private TrieNode helper(String word,int start,TrieNode pointer){
if(word.length() == start) return pointer;
char c = word.charAt(start);
if(pointer.children[c - 'a'] == null) return null;
return helper(word,start+1,pointer.children[c - 'a']);
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
TrieNode ws = root;
ws = helper(prefix,0,ws);
return ws == null ? false : true;
}
}
public class Frequency {
public int getFrequency(String[] article, int n, String word) {
// write code here
Trie trie = new Trie();
for(String s : article){
trie.insert(s);
}
return trie.search(word);
}
}
70、整数对查找
题目描述
请设计一个高效算法,找出数组中两数之和为指定值的所有整数对。
给定一个int数组A和数组大小n以及需查找的和sum,请返回和为sum的整数对的个数。保证数组大小小于等于3000。
测试样例:
[1,2,3,4,5],5,6
返回:2
import java.util.*;
public class FindPair {
public int countPairs(int[] A, int n, int sum) {
// write code here
Arrays.sort(A);
int lo = 0,hi = n-1;
int cnt = 0;
int k1 = 1,k2 = 1;
while(lo < hi){
if(A[lo] + A[hi] > sum) {
hi--;
while(lo < hi && A[hi] == A[hi+1])hi--;
}
else if(A[lo] + A[hi] < sum) {
lo++;
while(lo < hi && A[lo] == A[lo-1])lo++;
}
else{
while(lo < hi && A[lo] == A[lo+1]){
lo++;
k1++;
}
while(lo < hi && A[hi] == A[hi-1]){
hi--;
k2++;
}
if(A[lo] == A[hi]){
cnt += k1*(k1-1)/2;
}
else cnt += k1*k2;
lo++;
hi--;
k1 = 1;
k2 = 1;
}
}
return cnt;
}
}
71、树转链表
题目描述
有一个类似结点的数据结构TreeNode,包含了val属性和指向其它结点的指针。其可以用来表示二叉查找树(其中left指针表示左儿子,right指针表示右儿子)。请编写一个方法,将二叉查找树转换为一个链表,其中二叉查找树的数据结构用TreeNode实现,链表的数据结构用ListNode实现。
给定二叉查找树的根结点指针root,请返回转换成的链表的头指针。
import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}*/
public class Converter {
ListNode tail;
private void InOrder(TreeNode root){
if(root != null){
InOrder(root.left);
int val = root.val;
ListNode node = new ListNode(val);
tail.next = node;
tail = node;
InOrder(root.right);
}
}
public ListNode treeToList(TreeNode root) {
// write code here
ListNode headNode = new ListNode(0);
tail = headNode;
InOrder(root);
return headNode.next;
}
}
72、另类加法
题目描述
请编写一个函数,将两个数字相加。不得使用+或其他算数运算符。
给定两个int A和B。请返回A+B的值
测试样例:
1,2
返回:3
import java.util.*;
/**
1和1相加才会产生进位
循环
第一步不考虑进位,异或
第二步考虑进位,与运算然后左移1位
第一步和第二步的结果加起来
直到不产生进位
*/
public class UnusualAdd {
public int addAB(int A, int B) {
// write code here
int sum,carry;
do{
sum = A ^ B;
carry = (A & B) << 1;
A = sum;
B = carry;
}while(B!=0);
return A;
}
}
73、2的个数
题目描述
请编写一个方法,输出0到n(包括n)中数字2出现了几次。
给定一个正整数n,请返回0到n的数字中2出现了几次。
测试样例:
10
返回:1
import java.util.*;
public class Count2 {
private int countNumberOfKs(int n,int k) {
// write code here
int res = 0;
for (long m = 1;m <= n;m *= 10) {
long tmp1 = n / m, tmp2 = n%m;
res += (tmp1 + 10-k-1) / 10 * m + (tmp1 % 10 == k ? 1:0)*(tmp2 + 1);
}
return res;
}
public int countNumberOf2s(int n){
return countNumberOfKs(n,2);
}
}
74、下一个较大元素
题目描述
现在我们有一个int数组,请你找出数组中每个元素的下一个比它大的元素。
给定一个int数组A及数组的大小n,请返回一个int数组,代表每个元素比他大的下一个元素,若不存在则为-1。保证数组中元素均为正整数。
测试样例:
[11,13,10,5,12,21,3],7
返回:[13,21,12,12,21,-1,-1]
import java.util.*;
/**
反向遍历数组
借助一个辅助栈。
循环:如果栈不为空,当前元素大于栈顶元素,则继续出栈。
如果元素小于栈顶元素,则记录下一个比它大的元素为栈顶元素,然后入栈。
*/
public class NextElement {
public int[] findNext(int[] A, int n) {
// write code here
Stack<Integer> st = new Stack();
for(int i=n-1;i>=0;i--){
int x = A[i];
while(!st.isEmpty() && st.peek() <= x){
st.pop();
}
A[i] = st.isEmpty() ? -1:st.peek();
st.push(x);
}
return A;
}
}
75、下一个较大元素II
题目描述
现在有一个数组,请找出数组中每个元素的后面比它大的最小的元素,若不存在则为-1。
给定一个int数组A及数组的大小n,请返回每个元素所求的值组成的数组。保证A中元素为正整数,且n小于等于1000。
测试样例:
[11,13,10,5,12,21,3],7
[12,21,12,12,21,-1,-1]
import java.util.*;
public class NextElement {
public int[] findNext(int[] A, int n) {
// write code here
int[] ans = new int[n];
ans[n-1] = -1;
for(int i=n-2;i>=0;i--){
ans[i] = -1;
for(int j=i+1;j<n;j++){
if(A[j] > A[i]){
ans[i] = ans[i] == -1 ? A[j] : Math.min(A[j],ans[i]);
}
}
}
return ans;
}
}
76、单词最近距离
题目描述
有一篇文章内含多个单词,现给定两个单词,请设计一个高效算法,找出文中这两个单词的最短距离(即最少相隔的单词数,也就是两个单词在文章中位置的差的绝对值)。
给定一个string数组article,代表所给文章,同时给定文章的单词数n和待查找的两个单词x和y。请返回两个单词的最短距离。保证两个单词均在文中出现且不相同,同时保证文章单词数小于等于1000。
import java.util.*;
public class Distance {
public int getDistance(String[] article, int n, String x, String y) {
// write code here
int px = -1,py = -1;
int mindis = 1000;
for(int i=0;i<n;i++){
if(article[i].equals(x)){
px = i;
}
else if(article[i].equals(y)){
py = i;
}
if(px != -1 && py != -1){
if(px < py){
mindis = Math.min(py-px,mindis);
px = -1;
}
else{
mindis = Math.min(px-py,mindis);
py = -1;
}
}
}
return mindis;
}
}
77、最长合成字符串
题目描述
有一组单词,请编写一个程序,在数组中找出由数组中字符串组成的最长的串A,即A是由其它单词组成的(可重复)最长的单词。
给定一个string数组str,同时给定数组的大小n。请返回最长单词的长度,保证题意所述的最长单词存在。
测试样例:
[“a”,“b”,“c”,“ab”,“bc”,“abc”],6
返回:3
import java.util.*;
/**
首先对字符串按照长度进行排序,然后判断是否可由其他的字符串合成
注意的问题不可与自身比较,所以需要记录候选字符串的索引值,递归时排除。
*/
public class LongestString {
private boolean isComposed(String[] str,String s,int index){
if("".equals(s)) return true;
for(int i=0;i<str.length;i++){
if(i != index && s.startsWith(str[i])){
int sublen = str[i].length();
if(isComposed(str,s.substring(sublen),index)){
return true;
}
}
}
return false;
}
public int getLongest(String[] str, int n) {
// write code here
Arrays.sort(str,(a,b)->{
return a.length()-b.length();
});
for(int i=n-1;i>=0;i--){
if(isComposed(str,str[i],i)){
return str[i].length();
}
}
return 0;
}
}
78、子串判断
题目描述
现有一个小写英文字母组成的字符串s和一个包含较短小写英文字符串的数组p,请设计一个高效算法,对于p中的每一个较短字符串,判断其是否为s的子串。
给定一个string数组p和它的大小n,同时给定string s,为母串,请返回一个bool数组,每个元素代表p中的对应字符串是否为s的子串。保证p中的串长度小于等于8,且p中的串的个数小于等于500,同时保证s的长度小于等于1000。
测试样例:
[“a”,“b”,“c”,“d”],4,“abc”
返回:[true,true,true,false]
import java.util.*;
public class Substr {
public boolean[] chkSubStr(String[] p, int n, String s) {
// write code here
boolean[] ans = new boolean[n];
for(int i=0;i<n;i++){
ans[i] = s.indexOf(p[i]) >= 0;
}
return ans;
}
}
79、实时中位数
题目描述
现有一些随机生成的数字要将其依次传入,请设计一个高效算法,对于每次传入一个数字后,算出当前所有传入数字的中位数。(若传入了偶数个数字则令中位数为第n/2小的数字,n为已传入数字个数)。
给定一个int数组A,为传入的数字序列,同时给定序列大小n,请返回一个int数组,代表每次传入后的中位数。保证n小于等于1000。
测试样例:
[1,2,3,4,5,6],6
返回:[1,1,2,2,3,3]
import java.util.*;
public class Middle {
class MedianFinder {
PriorityQueue<Integer> lo ;
PriorityQueue<Integer> hi ;
public MedianFinder() {
lo = new PriorityQueue((a,b)->((int) b - (int) a));
hi = new PriorityQueue();
}
public void addNum(int num) {
lo.add(num);
hi.add(lo.poll());
if(lo.size() < hi.size()){
lo.add(hi.poll());
}
}
public int findMedian() {
return lo.peek();
}
}
public int[] getMiddle(int[] A, int n) {
// write code here
MedianFinder mf = new MedianFinder();
int[] medians = new int[n];
for(int i=0;i<n;i++){
mf.addNum(A[i]);
medians[i] = mf.findMedian();
}
return medians;
}
}
80、字符串变换
题目描述
现有一个字典,同时给定字典中的两个字符串s和t,给定一个变换,每次可以改变字符串中的任意一个字符,请设计一个算法,计算由s变换到t所需的最少步数,同时需要满足在变换过程中的每个串都是字典中的串。
给定一个string数组dic,同时给定数组大小n,串s和串t,请返回由s到t变换所需的最少步数。若无法变换到t则返回-1。保证字符串长度均小于等于10,且字典中字符串数量小于等于500。
测试样例:
[“abc”,“adc”,“bdc”,“aaa”],4,”abc”,“bdc”
返回:2
import java.util.*;
public class Change {
public int countChanges(String[] dic, int n, String s, String t) {
// write code here
HashMap<String,ArrayList<String>> dict = new HashMap();
for(String str : dic){
int len = str.length();
for(int i=0;i<len;i++){
String sub = str.substring(0,i)+"*"+str.substring(i+1);
ArrayList<String> value = dict.getOrDefault(sub,new ArrayList());
if(!value.contains(str)){
value.add(str);
dict.put(sub,value);
}
}
}
if(s.equals(t)) return 0;
Queue<String> q = new LinkedList();
HashMap<String,Boolean> visited = new HashMap();
visited.put(s,true);
q.offer(s);
int level = 0;
while(!q.isEmpty()){
int size = q.size();
for(int j=0; j< size;j++){
String cur = q.poll();
for(int i=0;i<cur.length();i++){
String patt = cur.substring(0,i)+"*"+cur.substring(i+1);
ArrayList<String> neighbors = dict.get(patt);
if(neighbors != null){
for(String neighbor : neighbors){
if(!visited.containsKey(neighbor)){
q.offer(neighbor);
visited.put(neighbor,true);
if(neighbor.equals(t)){
return level+1;
}
}
}
}
}
}
level++;
}
return -1;
}
}
81、最大子方阵
题目描述
有一个方阵,其中每个单元(像素)非黑即白(非0即1),请设计一个高效算法,找到四条边颜色相同的最大子方阵。
给定一个01方阵mat,同时给定方阵的边长n,请返回最大子方阵的边长。保证方阵边长小于等于100。
测试样例:
[[1,1,1],[1,0,1],[1,1,1]],3
返回:3
import java.util.*;
/*
暴力解法
*/
public class SubMatrix {
public int maxSubMatrix(int[][] mat, int n) {
// write code here
int max = 1;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
for(int k=j+1;k<n;k++){
if(judge(mat,i,j,k) && k-j+1 > max){
max = k-j+1;
}
}
}
}
return max;
}
private boolean judge(int[][] mat,int i,int j,int k){
if(i + k - j >= mat.length){
return false;
}
int color = mat[i][j];
for(int m=j;m<=k;m++){
if(mat[i][m] != color || mat[i+k-j][m] != color) return false;
}
for(int m=i+1;m<i+k-j;m++){
if(mat[m][j] != color || mat[m][k] != color) return false;
}
return true;
}
}
82、最大和子矩阵
题目描述
有一个正整数和负整数组成的NxN矩阵,请编写代码找出元素总和最大的子矩阵。请尝试使用一个高效算法。
给定一个int矩阵mat和矩阵的阶数n,请返回元素总和最大的子矩阵的元素之和。保证元素绝对值小于等于100000,且矩阵阶数小于等于200。
测试样例:
[[1,2,-3],[3,4,-5],[-5,-6,-7]],3
返回:10
import java.util.*;
/**
子问题是求子数组的最大和
二重循环,还有一个循环,将第j行加到第i行
*/
public class SubMatrix {
public int sumOfSubMatrix(int[][] mat, int n) {
// write code here
if(mat == null || n == 0) return 0;
int max = Integer.MIN_VALUE;
for(int i=0 ; i<n; i++){
max = Math.max(maxSubArray(mat[i]),max);
for(int j=i+1 ; j < n;j++){
for(int k = 0;k < n;k++){
mat[i][k] += mat[j][k];
}
max = Math.max(maxSubArray(mat[i]),max);
}
}
return max;
}
public int maxSubArray(int[] nums) {
if(nums.length == 0) return 0;
int maxSum=nums[0], thisSum=0;
for(int i=0;i < nums.length; i++){
if(thisSum < 0){
thisSum = 0;
}
thisSum += nums[i];
if(thisSum > maxSum){
maxSum = thisSum;
}
}
return maxSum;
}
}
83、最大字母矩阵
题目描述
有一个单词清单,请设计一个高效算法,计算由清单中单词组成的最大子矩阵,要求矩阵中的行和列都是清单中的单词。
给定一个string数组dic,代表单词清单,同时给定清单的大小n,请返回最大子矩阵的面积。保证单词清单的大小小于等于50,且某一长度的串的数量小于等于12。
测试样例:
[“aaa”,“aaa”,“aaa”,“bb”,“bb”]
返回:9
import java.util.*;
public class AlphaMatrix {
public int findAlphaMatrix(String[] dic, int n) {
// write code here
HashMap<String,Integer> hm = new HashMap();
for(String s:dic){
hm.put(s,hm.getOrDefault(s,0)+1);
}
int max = 0;
for(String s:dic){
max = Math.max(max,hm.get(s) * s.length());
}
return max;
}
}