Skip to content

Commit a2f7f35

Browse files
[N-0] refactor 8
1 parent 2f04ea5 commit a2f7f35

File tree

2 files changed

+208
-138
lines changed

2 files changed

+208
-138
lines changed

src/main/java/com/fishercoder/solutions/_8.java

Lines changed: 135 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -13,169 +13,166 @@
1313
import java.util.Set;
1414

1515
/**
16+
* 8. String to Integer (atoi)
17+
*
1618
* Implement atoi to convert a string to an integer.
17-
Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.
18-
Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
19-
20-
Requirements for atoi:
21-
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
22-
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
23-
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
24-
If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.*/
25-
public class _8 {
26-
public int myAtoi_clean_version(String str) {
27-
int p = 0;
28-
int result = 0;
29-
while (p < str.length() && Character.isWhitespace(str.charAt(p))) {
30-
p++;
31-
}
32-
if (p == str.length()) {
33-
return 0;
34-
}
35-
boolean negativeFlag = (str.charAt(p) == '-');
36-
if (str.charAt(p) == '+' || str.charAt(p) == '-') {
37-
p++;
38-
}
39-
for (; p < str.length(); p++) {
40-
if (str.charAt(p) > '9' || str.charAt(p) < '0') {
41-
break;
42-
} else {
43-
int digit = str.charAt(p) - '0';
44-
if (!negativeFlag && result > (Integer.MAX_VALUE - digit) / 10) {
45-
return Integer.MAX_VALUE;
46-
} else if (negativeFlag && result < (Integer.MIN_VALUE + digit) / 10) {
47-
return Integer.MIN_VALUE;
48-
}
49-
result = result * 10 + (negativeFlag ? -digit : digit);
50-
}
51-
}
52-
return result;
53-
}
19+
*
20+
* Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.
21+
* Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
22+
*
23+
* Requirements for atoi:
24+
* The function first discards as many whitespace characters as necessary until the first non-whitespace character is found.
25+
* Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
26+
* The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
27+
* If the first sequence of non-whitespace characters in str is not a valid integral number,
28+
* or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
29+
* If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.*/
5430

55-
public static void main(String... strings) {
56-
_8 test = new _8();
57-
// String str = "2147483648";
58-
// String str = "+-2";//a really interesting test case, you never know how stupid one's input could be like, this is to challenge your program to be more robust. It's expecting to return 0 for this case which means it's not a valid number
59-
// String str = "+";
60-
// String str = "abc";
61-
// String str = "1";
62-
// String str = "-2147483648";
63-
// String str = "++1";//I'm really amazed by OJ's test case variety, it's expecting 0 in this case
64-
// String str = "-2147483649";
65-
String str = "9223372036854775809";
66-
System.out.println(test.myAtoi(str));
67-
68-
69-
// System.out.println(Double.parseDouble("1.2098"));
70-
// System.out.println(Integer.parseInt("123456789"));
71-
}
72-
73-
//Eventually, made it AC'ed, lots of corner cases, but now, really felt much easier and the though process is super clear than the first time I tried to solve it which was 3~4 years ago from now. 8/9/2016
74-
public int myAtoi(String str) {
75-
//case 1: str is greater than Integer.MAX_VALUE, return Integer.MAX_VALUE as the question states it
31+
public class _8 {
7632

77-
//case 2: str is smaller than Integer.MIN_VALUE, return Integer.MIN_VALUE as the question states it
33+
public static class Solution1 {
34+
/**Eventually, made it AC'ed, lots of corner cases, but now,
35+
* really felt much easier and the though process is super clear than the first time I tried to solve it which was 3~4 years ago from now.
36+
* - 8/9/2016
37+
* */
38+
public int myAtoi(String str) {
39+
//case 1: str is greater than Integer.MAX_VALUE, return Integer.MAX_VALUE as the question states it
7840

79-
//case 3: str contains non-numeric values
41+
//case 2: str is smaller than Integer.MIN_VALUE, return Integer.MIN_VALUE as the question states it
8042

81-
//case 4: there're many leading whitespace characters which we'll have to ignore
43+
//case 3: str contains non-numeric values
8244

83-
//case 5: when finding the first non-whitespace character, it could possibly be a '+' or '-' sign, after that, we parse all the consecutive numbers
45+
//case 4: there're many leading whitespace characters which we'll have to ignore
8446

85-
str = str.trim();//cut off its leading and trailing whitespace characters
86-
if (str == null || str.isEmpty()) {
87-
return 0;
88-
}
89-
Set<Character> numbers = new HashSet();
90-
for (int i = 0; i < 10; i++) {
91-
numbers.add(Character.forDigit(i, 10));
92-
}
47+
//case 5: when finding the first non-whitespace character, it could possibly be a '+' or '-' sign, after that, we parse all the consecutive numbers
9348

94-
char[] chars = str.toCharArray();
95-
StringBuilder sb = new StringBuilder();
96-
boolean negative;
97-
int minuSignCount = 0;
98-
int plusSignCount = 0;
99-
int i = 0;
100-
while (i < chars.length) {
101-
if (chars[i] == '-') {
102-
minuSignCount++;
103-
i++;
104-
} else if (chars[i] == '+') {
105-
plusSignCount++;
106-
i++;
107-
} else {
108-
break;
49+
str = str.trim();//cut off its leading and trailing whitespace characters
50+
if (str == null || str.isEmpty()) {
51+
return 0;
52+
}
53+
Set<Character> numbers = new HashSet();
54+
for (int i = 0; i < 10; i++) {
55+
numbers.add(Character.forDigit(i, 10));
10956
}
110-
}
111-
if ((plusSignCount > 0 && minuSignCount > 0) || minuSignCount > 1 || plusSignCount > 1) {
112-
return 0;
113-
}
114-
negative = minuSignCount % 2 != 0;
115-
if (i >= chars.length) {
116-
return 0;
117-
}
11857

119-
//it might be a floating number, so consider '.'
120-
int period = 0;
121-
while (i < chars.length && numbers.contains(chars[i])) {
122-
if (chars[i] == '.') {
123-
period++;
58+
char[] chars = str.toCharArray();
59+
StringBuilder sb = new StringBuilder();
60+
boolean negative;
61+
int minuSignCount = 0;
62+
int plusSignCount = 0;
63+
int i = 0;
64+
while (i < chars.length) {
65+
if (chars[i] == '-') {
66+
minuSignCount++;
67+
i++;
68+
} else if (chars[i] == '+') {
69+
plusSignCount++;
70+
i++;
71+
} else {
72+
break;
73+
}
12474
}
125-
if (period > 1) {
126-
break;
75+
if ((plusSignCount > 0 && minuSignCount > 0) || minuSignCount > 1 || plusSignCount > 1) {
76+
return 0;
77+
}
78+
negative = minuSignCount % 2 != 0;
79+
if (i >= chars.length) {
80+
return 0;
12781
}
128-
sb.append(chars[i++]);
129-
}
13082

131-
if (sb == null || sb.length() == 0) {
132-
return 0;
133-
}
83+
//it might be a floating number, so consider '.'
84+
int period = 0;
85+
while (i < chars.length && numbers.contains(chars[i])) {
86+
if (chars[i] == '.') {
87+
period++;
88+
}
89+
if (period > 1) {
90+
break;
91+
}
92+
sb.append(chars[i++]);
93+
}
13494

135-
int result = 0;
136-
if (period > 0) {
137-
//use Double to parse
138-
try {
139-
result = (int) Double.parseDouble(sb.toString());
140-
} catch (Exception e) {
141-
System.out.println(e);
95+
if (sb == null || sb.length() == 0) {
96+
return 0;
14297
}
143-
} else {
144-
//use Long to parse to handle integer overflow case
145-
long temp = 0;
146-
if (sb.length() >= Long.toString(Long.MAX_VALUE).length() && negative) {
147-
return Integer.MIN_VALUE;
148-
} else if (sb.length() >= Long.toString(Long.MAX_VALUE).length() && !negative) {
149-
return Integer.MAX_VALUE;
150-
} else {
98+
99+
int result = 0;
100+
if (period > 0) {
101+
//use Double to parse
151102
try {
152-
temp = Long.parseLong(sb.toString());
103+
result = (int) Double.parseDouble(sb.toString());
153104
} catch (Exception e) {
154-
if (sb.length() >= Integer.MAX_VALUE) {
155-
result = Integer.MAX_VALUE;
156-
}
105+
System.out.println(e);
157106
}
158-
if (temp > (long) Integer.MAX_VALUE + 1) {
159-
if (!negative) {
160-
return Integer.MAX_VALUE;
161-
} else {
162-
return Integer.MIN_VALUE;
163-
}
164-
} else if (temp == (long) Integer.MAX_VALUE + 1 && negative) {
107+
} else {
108+
//use Long to parse to handle integer overflow case
109+
long temp = 0;
110+
if (sb.length() >= Long.toString(Long.MAX_VALUE).length() && negative) {
165111
return Integer.MIN_VALUE;
166-
} else if (temp == (long) Integer.MAX_VALUE + 1) {
112+
} else if (sb.length() >= Long.toString(Long.MAX_VALUE).length() && !negative) {
167113
return Integer.MAX_VALUE;
168-
} else if (temp < Integer.MIN_VALUE) {
169-
result = Integer.MIN_VALUE;
170114
} else {
171-
result = (int) temp;
115+
try {
116+
temp = Long.parseLong(sb.toString());
117+
} catch (Exception e) {
118+
if (sb.length() >= Integer.MAX_VALUE) {
119+
result = Integer.MAX_VALUE;
120+
}
121+
}
122+
if (temp > (long) Integer.MAX_VALUE + 1) {
123+
if (!negative) {
124+
return Integer.MAX_VALUE;
125+
} else {
126+
return Integer.MIN_VALUE;
127+
}
128+
} else if (temp == (long) Integer.MAX_VALUE + 1 && negative) {
129+
return Integer.MIN_VALUE;
130+
} else if (temp == (long) Integer.MAX_VALUE + 1) {
131+
return Integer.MAX_VALUE;
132+
} else if (temp < Integer.MIN_VALUE) {
133+
result = Integer.MIN_VALUE;
134+
} else {
135+
result = (int) temp;
136+
}
172137
}
173138
}
139+
140+
if (negative) {
141+
result = -result;
142+
}
143+
return result;
174144
}
145+
}
175146

176-
if (negative) {
177-
result = -result;
147+
public static class Solution2 {
148+
public int myAtoi(String str) {
149+
int p = 0;
150+
int result = 0;
151+
while (p < str.length() && Character.isWhitespace(str.charAt(p))) {
152+
p++;
153+
}
154+
if (p == str.length()) {
155+
return 0;
156+
}
157+
boolean negativeFlag = (str.charAt(p) == '-');
158+
if (str.charAt(p) == '+' || str.charAt(p) == '-') {
159+
p++;
160+
}
161+
for (; p < str.length(); p++) {
162+
if (str.charAt(p) > '9' || str.charAt(p) < '0') {
163+
break;
164+
} else {
165+
int digit = str.charAt(p) - '0';
166+
if (!negativeFlag && result > (Integer.MAX_VALUE - digit) / 10) {
167+
return Integer.MAX_VALUE;
168+
} else if (negativeFlag && result < (Integer.MIN_VALUE + digit) / 10) {
169+
return Integer.MIN_VALUE;
170+
}
171+
result = result * 10 + (negativeFlag ? -digit : digit);
172+
}
173+
}
174+
return result;
178175
}
179-
return result;
180176
}
177+
181178
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.fishercoder;
2+
3+
import com.fishercoder.solutions._8;
4+
import org.junit.BeforeClass;
5+
import org.junit.Test;
6+
7+
import static org.junit.Assert.assertEquals;
8+
9+
public class _8Test {
10+
private static _8.Solution1 solution1;
11+
private static _8.Solution2 solution2;
12+
13+
@BeforeClass
14+
public static void setup() {
15+
solution1 = new _8.Solution1();
16+
solution2 = new _8.Solution2();
17+
}
18+
19+
@Test
20+
public void test1() {
21+
assertEquals(2147483647, solution1.myAtoi("2147483648"));
22+
assertEquals(2147483647, solution2.myAtoi("2147483648"));
23+
}
24+
25+
@Test
26+
public void test2() {
27+
assertEquals(0, solution1.myAtoi("+-2"));
28+
assertEquals(0, solution2.myAtoi("+-2"));
29+
}
30+
31+
@Test
32+
public void test3() {
33+
assertEquals(0, solution1.myAtoi("+"));
34+
assertEquals(0, solution2.myAtoi("+"));
35+
}
36+
37+
@Test
38+
public void test4() {
39+
assertEquals(0, solution1.myAtoi("abc"));
40+
assertEquals(0, solution2.myAtoi("abc"));
41+
}
42+
43+
@Test
44+
public void test5() {
45+
assertEquals(1, solution1.myAtoi("1"));
46+
assertEquals(1, solution2.myAtoi("1"));
47+
}
48+
49+
@Test
50+
public void test6() {
51+
assertEquals(-2147483648, solution1.myAtoi("-2147483648"));
52+
assertEquals(-2147483648, solution2.myAtoi("-2147483648"));
53+
}
54+
55+
@Test
56+
public void test7() {
57+
assertEquals(0, solution1.myAtoi("++1"));
58+
assertEquals(0, solution2.myAtoi("++1"));
59+
}
60+
61+
@Test
62+
public void test8() {
63+
assertEquals(-2147483648, solution1.myAtoi("-2147483649"));
64+
assertEquals(-2147483648, solution2.myAtoi("-2147483649"));
65+
}
66+
67+
@Test
68+
public void test9() {
69+
assertEquals(2147483647, solution1.myAtoi("9223372036854775809"));
70+
assertEquals(2147483647, solution2.myAtoi("9223372036854775809"));
71+
}
72+
73+
}

0 commit comments

Comments
 (0)