面试题36:第一个只出现一次的字符位置
在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置
代码:(借助哈希)
import java.util.LinkedHashMap;
public class Solution {
public int FirstNotRepeatingChar(String str) {
LinkedHashMap <Character, Integer> map = new LinkedHashMap<Character, Integer>();
for(int i=0;i<str.length();i++) {
if(map.containsKey(str.charAt(i))) {
int num = map.get(str.charAt(i));
num = num+10000;
map.put(str.charAt(i), num);
}else {
map.put(str.charAt(i), i);
}
}
int pos=-1;
for(int i=0;i<str.length();i++) {
if(map.get(str.charAt(i))<10000) {
if(pos==-1) {
pos=i;
}else {
pos = Math.min(pos, i);
}
}
}
return pos;
}
}
面试题37:数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
示例1
输入
1,2,3,4,5,6,7,0
输出
7
代码1:(牛客超时)
public int InversePairs(int [] array) {
if(array == null) return 0;
int count=0;
for(int i=0;i<array.length-1;i++) {
for(int j=i+1;j<array.length;j++) {
if(array[i]>array[j]) count++;
}
}
int r = count%1000000007;
return r;
}
代码2:
面试题38:两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。
代码:
import java.util.Stack;
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1==null || pHead2==null) return null;
//借助栈或者哈希都可以
Stack<ListNode> s1 = new Stack<ListNode>();
Stack<ListNode> s2 = new Stack<ListNode>();
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while(p1 != null || p2 != null) {
if(p1 != null) {
s1.push(p1);
p1 = p1.next;
}
if(p2 != null) {
s2.push(p2);
p2 = p2.next;
}
}
p1=null;
while(!s1.isEmpty() && !s2.isEmpty()) {
if(s1.peek() == s2.peek()){
p1 = s1.peek();
s1.pop();
s2.pop();
}else{
break;
}
}
return p1;
}
}
面试题39:数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数。
代码1:简单的从前到后的遍历
public class Solution {
public int GetNumberOfK(int [] array , int k) {
if(array==null) return 0;
int count=0;
int flag=0;
for(int i=0;i<array.length;i++) {
if(array[i] == k ) {
flag=1;
count++;
}else if(flag==1){
break;
}
}
return count;
}
}
代码2:融合二分查找法
面试题40:二叉树的深度
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
代码:
public class Solution {
public int TreeDepth(TreeNode root) {
if(root ==null) return 0;
int num=0;
num = digui(root,num);//当时调试的时候是这里出的问题
return num;
}
public int digui(TreeNode root,int num) {
if(root==null) return num;
num = num+1;
int num1 = digui(root.left,num);//注意num的值传递
int num2 = digui(root.right,num);
num = num1>num2? num1:num2;
return num;
}
}
注意:这道题错的位置在加注释的地方,这道题本身不难,但是关于递归的思想和java函数的值传递的本质要有更深刻的认识!!!
面试题41:平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
代码:
public class Solution {
public boolean IsBalanced_Solution(TreeNode root) {
if(root==null) return true;
return getDepth(root)!=-1;
}
public int getDepth(TreeNode root) {
if(root==null) return 0;
int left = getDepth(root.left);
if(left==-1) return -1;
int right = getDepth(root.right);
if(right==-1) return -1;
if(left-right>=-1 && left-right<=1) {
return 1+Math.max(left, right) ;
}else {
return -1;
}
}
}
知识点:
1. 平衡二叉树:如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树
面试题42:数组中只出现一次的数字
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
代码1:HashMap
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.LinkedHashMap;
import java.util.Set;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array==null) return;
LinkedHashMap<Integer,Integer> h = new LinkedHashMap<>();
for(int i=0;i<array.length;i++) {
if(h.containsKey(array[i])) {
h.remove(array[i],1);
}else {
h.put(array[i], 1);
}
}
int [] num ;
num = new int[2];
Set<Integer> s = h.keySet();
int j=0;
for(int i:s) {
num[j++]=i;
}
num1[0]=num[0];
num2[0]=num[1];
}
}
代码2:异或
面试题43:和为S的连续正数序列
>
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序.
代码:
import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > a = new ArrayList<ArrayList<Integer> >();
if(sum<=2) return a;
int small=1,big=2;
int temp = big+small;
while(small<=sum/2) {
while(temp<sum) {
big+=1;
temp+=big;
}
if(temp==sum) {
ArrayList<Integer> t = new ArrayList<Integer>();
for(int i=small;i<=big;i++) {
t.add(i);
}
a.add(t);
}
temp-=small;
small+=1;
}
return a;
}
}
面试题44:和为S的两个数字
>
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。(也就是最先找到的)
输出描述:
对应每个测试案例,输出两个数,小的先输出。
代码:
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
ArrayList<Integer> a = new ArrayList<Integer>();
if (array == null || array.length < 2) {
return a;
}
int i=0,j=array.length-1;
while(i<j){
if(array[i]+array[j]==sum){
a.add(array[i]);
a.add(array[j]);
return a;
}else if(array[i]+array[j]>sum){
j--;
}else{
i++;
}
}
return a;
}
}
注意:使用的是夹逼准则
面试题45:左旋转字符串
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
代码:
public class Solution {
public String LeftRotateString(String str,int n) {
if(str==null || str.length()==0) return str;
if(n<=0) return str;
int length = str.length();
String s,s1,s2;
if(n<length) {
s1 = str.substring(0, n);//注意:substring(,)后面的索引是不包括的,所以这里是n而不是n-1
s2 = str.substring(n);
s = s2.concat(s1);
}else if(n>length) {
int num = n%length;
s1 = str.substring(0, num);
s2 = str.substring(num);
s = s2.concat(s1);
}else {
s = str;
}
return s;
}
}
面试题46:翻转单词顺序列
牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?
代码1:(未通过)但是我感觉方法是可以的
public class Question46 {
public String ReverseSentence(String str) {
if(str==null || str.length()==0) return str;
String [] a;
int num=0;//计算空格的个数
for(int i=0;i<str.length();i++) {
if(str.charAt(i)==' ') {
num++;
}
}
if(num<1) return str;//处理单个单词的情况
a = new String[num+1];
int i1=0,j1=str.length()-1;
int i2=0,j2=str.length()-1;
int n = 0;
while(i2<=j2) {
if(str.charAt(i2)==' ' && str.charAt(j2)==' ') {
a[n]=str.substring(j2+1, j1);//2动1不动
a[a.length-1-n] = str.substring(i1, i2);
n++;
i2+=1;j2-=1;
i1=i2;j1=j2;
continue;
}
i2++;
j2--;
}
if(num%2==0) {
a[a.length/2] = str.substring(i1, j1+1); //处理奇数的情况
}
String s =a[0];
for(int i=1;i<a.length;i++) {
s.concat(" ");
s.concat(a[i]);
}
return s;
}
}
代码2:
import java.util.Arrays;
public class Solution {
public String ReverseSentence(String str) {
if(str==null || str.length()==0) return str;
char [] a;
a = str.toCharArray();
int length=a.length;
//将整个字符串翻转
reverse(a,0,length-1);
//将单个单词内部进行翻转
int p1 = -1;
for(int p2=0;p2<length;p2++) {
if(a[p2]==' ') {
reverse(a,p1+1,p2-1);
p1=p2;
}
}
reverse(a,p1+1,length-1);
return new String(a);
}
public void reverse(char [] a,int p1,int p2) {
while(p1<p2) {
char temp=a[p1];
a[p1] = a[p2];
a[p2] = temp;
p1++;
p2--;
}
}
}
注意:关于字符串和字符数组之间的转化有很多捷径,所以不需要一直自己循环!