剑指offer 第 49题
今日第一题:
把字符串转化为整数
题目描述
将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0
public class Solution {
public int StrToInt(String str) {
if(str==null||str.length()==0) return 0;
if(str.charAt(0)=='-')
{
boolean b = str.substring(1,str.length()).matches("[0-9]{1,}");
if(!b) return 0;
return convert(str.substring(1,str.length()),false);
}else{
String s=null;
if(str.charAt(0)=='+')
{
s = str.substring(1,str.length());
}else{
s = str;
}
boolean b = s.matches("[0-9]{1,}");
if(!b) return 0;
return convert(s,true);
}
}
private int convert(String str,boolean t)
{
int carry = 0;
for(int i=0;i<str.length();++i)
{
carry*=10;
carry += str.charAt(i)-'0';
}
if(!t) carry = -carry;
return carry;
}
}
数组中的重复数字
注意:数组内的数字 不会超过 n,因此可以不使用 hashMap 的方法
题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
public class Solution {
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
// Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
// 这里要特别注意~返回任意重复的一个,赋值duplication[0]
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
public boolean duplicate(int arr[],int length,int [] duplication) {
boolean[] map = new boolean[length];
for(int i=0;i<length;++i)
{
if(map[arr[i]]==true)
{
duplication[0] = arr[i];
return true;
}
map[arr[i]] = true;
}
return false;
}
}
构建乘积数组
题目描述
给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。
看了半天终于看懂了
链接:https://www.nowcoder.com/questionTerminal/94a4d381a68b47b7a8bed86f2975db46?f=discussion
来源:牛客网
B[0] = A[1] * A[2] * A[3] * A[4] *…*A[n-1] ;(没有A[0])
B[1 ]= A[0] * A[2] * A[3] * A[4] *…*A[n-1] ;(没有A[1])
B[2] = A[0] * A[1] * A[3] * A[4] *…*A[n-1] ;(没有A[2])
…
链接:https://www.nowcoder.com/questionTerminal/94a4d381a68b47b7a8bed86f2975db46?f=discussion
来源:牛客网
借助两个数组lefts和rights,一个记录B[i]值的左乘结果A[0]A[1]…*A[i-1],一个记录B[i]值的右乘结果A[i+1]A[i+2]…*A[n-1],然后B[i]=lefts[i]*rights[i];
import java.util.ArrayList;
public class Solution {
public int[] multiply(int[] A) {
int[] ans = new int[A.length];
ans[0] =1;
//计算左边数组
for(int i=1;i<ans.length;++i)
{
ans[i]=ans[i-1]*A[i-1];
}
//计算右边数组
int carry = 1;
for(int i=ans.length-2;i>=0;--i)
{
carry*=A[i+1];
ans[i]*=carry;
}
return ans;
}
}
这应该是最优解法了
第4题
表示数值的字符串
题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。
。。不想再看其他解法了,脑壳痛
public class Solution {
public boolean isNumeric(char[] str) {
try{
double b = Double.parseDouble(new String(str));
}catch(Exception e)
{
return false;
}
return true;
}
}
第五题
字符流中第一个不重复的字符
题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。
import java.util.*;
public class Solution {
private LinkedHashMap<Character,Integer> table = new LinkedHashMap();
//Insert one char from stringstream
public void Insert(char ch)
{
int i = table.getOrDefault(ch,0);
table.put(ch,i+1);
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
Set<Map.Entry<Character,Integer>> set = table.entrySet();
for(Map.Entry<Character,Integer> p:set)
{
if(p.getValue()==1)
{
return p.getKey();
}
}
return '#';
}
}
用 LinkeHashMap 保证有序
链表的环的入口节点
题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null
思路一: 使用 一个 HashSet ,如果添加失败,说明set已经存在该节点了,返回节点
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
import java.util.*;
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if(pHead==null) return pHead;
HashSet<ListNode> set = new HashSet();
ListNode begin = pHead;
while(begin!=null)
{
if(!set.add(begin))
{
return begin;
}
begin = begin.next;
}
return begin;
}
}
思路二:
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
import java.util.*;
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
ListNode fast = pHead;
ListNode slow = pHead;
while(fast!=null&&fast.next!=null)
{
fast = fast.next.next;
slow = slow.next;
if(fast==slow)
break;
}
if(fast==null||fast.next==null) return null;
slow = pHead;
while(fast!=slow)
{
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode deleteDuplication(ListNode pHead)
{
ListNode begin = new ListNode(-1);
begin.next = pHead;
ListNode end = pHead;
ListNode ans = begin;
while(end!=null)
{
if(end.next!=null&&end.val==end.next.val)
{
while(end.next!=null&&end.val==end.next.val)
{
end = end.next;
}
begin.next = end.next;
end = end.next;//记得要把记录删除掉,这个节点没用了,从下一个节点开始
}
else{
begin= begin.next;
end = end.next;
}
}
return ans.next;
}
}