面试题整理2

继续整理《Cracking the Coding Interview》。

17.4无判断max

请编写一个方法,找出两个数字中最大的那个。条件是不得使用if-else等比较和判断运算符。

给定两个int ab,请返回较大的一个数。若两数相同则返回任意一个。

通过判断a-b的符号来返回结果,考虑a-b溢出的情况。溢出的话一定异号,各种情形考虑到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Max {
public:
int flag(int x)
{
return (x >> 31) & 1;
}
int getMax(int a, int b)
{
int fa = flag(a);
int fb = flag(b);
int fc = flag(a - b);

int k = fa^fb;
int ans = 0;
if (k == 0)//如果同号
{
ans = 1 ^ fc;
}
else//如果异号
{
ans = 1 ^ fa;
}
return ans*a + (1 ^ ans)*b;
}
}wc;

17.5珠玑妙算

我们现在有四个槽,每个槽放一个球,颜色可能是红色(R)、黄色(Y)、绿色(G)或蓝色(B)。例如,可能的情况为RGGB(槽1为红色,槽2、3为绿色,槽4为蓝色),作为玩家,你需要试图猜出颜色的组合。比如,你可能猜YRGB。要是你猜对了某个槽的颜色,则算一次“猜中”。要是只是猜对了颜色但槽位猜错了,则算一次“伪猜中”。注意,“猜中”不能算入“伪猜中”。

给定两个string A和guess。分别表示颜色组合,和一个猜测。请返回一个int数组,第一个元素为猜中的次数,第二个元素为伪猜中的次数。

Leetcode上面的题。首先计算猜中的个数,然后没猜中的记录个数。注意考虑一些情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Result {
public:
vector<int> calcResult(string A, string guess)
{
int A_len = A.length();
int g_len = guess.length();

vector<int>res;
if (A_len != g_len)return res;
int ans1 = 0, ans2 = 0;

map<char, int>hax;
for (int i = 0; i < A_len; i++)
{
if (A[i] == guess[i])ans1++;
else
{
hax[A[i]]++;
}
}
for (int i = 0; i < g_len; i++)
{
if (A[i] == guess[i])continue;
else
{
if (hax[guess[i]])
{
ans2++;
hax[guess[i]]--;
}
}
}
res.push_back(ans1);
res.push_back(ans2);
return res;
}
};

17.6最小调整有序

有一个整数数组,请编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的。注意:n-m应该越小越好,也就是说,找出符合条件的最短序列。

给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的起点和终点。(原序列位置从0开始标号,若原序列有序,返回[0,0])。保证A中元素均为正整数。

首先找中间不符合排序的区间,然后记录这段区间下的最小值与最大值,往外面扩。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class Rearrange
{
public:

int find_left(vector<int>&A)
{
int sz = A.size();
for (int i = 0; i+1 < sz; i++)
{
if (A[i] > A[i + 1])return i;
}
return sz - 1;
}
int find_right(vector<int>&A)
{
int sz = A.size();
for (int i = sz - 1; i - 1 >= 0; i--)
{
if (A[i] < A[i - 1])return i;
}
return 0;
}
vector<int> findSegment(vector<int> A, int n)
{
int left = find_left(A);
int right = find_right(A);
if (left >= right)
{
vector<int>ans = { 0,0 };
return ans;
}
int minn = A[left], maxx = A[right];
for (int i = left; i <= right; i++)
{
minn = min(minn, A[i]);
maxx = max(maxx, A[i]);
}
while (left >= 0)
{
if (A[left] <= minn)
{
break;
}
left--;
}
left++;
while (right < A.size())
{
if (A[right] >= maxx)
{
break;
}
right++;
}
right--;
vector<int>res;
res.push_back(left);
res.push_back(right);
return res;
}
};

17.7数字发音

有一个非负整数,请编写一个算法,打印该整数的英文描述。

给定一个int x,请返回一个string,为该整数的英文描述。

这个也是Leetcode的原题,很麻烦,主要在于空格要考虑各种情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
class ToString 
{
public:
vector<string> bigs = { "","Thousand","Million" };
vector<string>digits = { "One","Two","Three","Four","Five","Six","Seven","Eight","Nine" };
vector<string>teens = { "Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen" };
vector<string>tens = { "Ten","Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety" };
string toString(int x)
{
if (x == 0)
{
return "Zero";
}
else if (x < 0)
{
return "Negative " + toString(-1 * x);
}

string res = "";
int cnt = 0;
while (x > 0)
{
if (x % 1000 != 0)
{
if(res.length())
res = num_to_string(x % 1000) + " " + bigs[cnt] + "," + res;
else
res = num_to_string(x % 1000) + " " + bigs[cnt];
}
x /= 1000;
cnt++;
}
while (*res.begin() == ' ')res.erase(res.begin());
while (*(res.end() - 1) == ' ')res.erase(res.end() - 1);
return res;
}
string num_to_string(int x)
{
string res = "";
if (x >= 100)
{
res = digits[x / 100 - 1] + " Hundred";
x = x % 100;
}
if (x >= 11 && x <= 19)
{
if(res.length())
res = res + " " + teens[x % 10 - 1];
else
res = teens[x % 10 - 1];
return res;
}
else if (x == 10 || x >= 20)
{
int num = x / 10;
x %= 10;
if(res.length())
res = res + " " + tens[num - 1];
else
res = tens[num - 1];
}
if (x)
{
if(res.length())
res = res + " " + digits[x - 1];
else
res = digits[x - 1];
}
return res;
}
};

17.13树转链表

有一个类似结点的数据结构TreeNode,包含了val属性和指向其它结点的指针。其可以用来表示二叉查找树(其中left指针表示左儿子,right指针表示右儿子)。请编写一个方法,将二叉查找树转换为一个链表,其中二叉查找树的数据结构用TreeNode实现,链表的数据结构用ListNode实现。

给定二叉查找树的根结点指针root,请返回转换成的链表的头指针。

中序递归遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class Converter
{
public:
ListNode *head = new ListNode(-1);
ListNode *pre = head;
ListNode* treeToList(TreeNode* root)
{
if (root)
{
treeToList(root->left);
pre->next = new ListNode(root->val);
pre = pre->next;
treeToList(root->right);
}
return head->next;
// write code here
}
};