您的位置:首页 > 其它

LeetCode Weekly Contest 47

2017-08-27 16:16 330 查看
自己还是太弱了quq,所以觉得看别人的代码来提高姿势水平比花很多时间想要有意义吧orz

每道题的解答都摘自Discuss,选的都是up vote最多的:

665. Non-decreasing Array

Given an array with 
n
 integers, your task is to check if it could become non-decreasing
by modifying at most 
1
 element.

We define an array is non-decreasing if 
array[i] <= array[i + 1]
 holds for every 
i
 (1
<= i < n).

Example 1:

Input: [4,2,3]
Output: True
Explanation: You could modify the first [code]4
to
1
to get a non-decreasing array.
[/code]

Example 2:

Input: [4,2,1]
Output: False
Explanation: You can't get a non-decreasing array by modify at most one element.


Note: The 
n
 belongs to [1, 10,000].

解答:

Java的:

class Solution {
public boolean checkPossibility(int[] nums) {
int n = nums.length, count = 0;

for (int i = 0; i + 1 < n; i++) {
if (nums[i] > nums[i + 1]) {
count++;
if (i > 0 && nums[i + 1] < nums[i - 1]) nums[i + 1] = nums[i];
else nums[i] = nums[i + 1];
}
}

return count <= 1;
}
}

另解:

"NON-DECREASING" is a double negative. This is the same as an array sorted in ascending order where 
nums[i]
<= nums[i+1]
.

Find the first exception to this rule where 
nums[i] > nums[i+1]
,

then see if the rest of the array is sorted in ascending order ( 
without
nums[i
4000
]
 ) XOR ( 
without nums[i+1]
 ).
class Solution {
public:
bool checkPossibility(vector<int>& nums) {
for (int i=0; i < nums.size()-1; i++){
if (nums[i] > nums[i+1]){

int temp = nums[i];
//
// "erase" nums[i], then check if nums is sorted without nums[i]
//
nums[i] = nums[i+1];
if (is_sorted(nums.begin(), nums.end())) { return true; }

//
// "erase" nums[i+1], then check if nums is sorted without nums[i+1]
//
nums[i+1] = nums[i] = temp;
if (is_sorted(nums.begin(), nums.end())) { return true; }

//
// nums is NOT sorted (without nums[i] XOR without nums[i+1])
//
return false;
}
}
return true;
}
};


666. Path Sum IV

If the depth of a tree is smaller than 
5
, then this tree can be represented by a list
of three-digits integers.

For each integer in this list:

The hundreds digit represents the depth 
D
 of this node, 
1
<= D <= 4.

The tens digit represents the position 
P
 of this node in the level it belongs
to, 
1 <= P <= 8
. The position is the same as that in a full binary tree.
The units digit represents the value 
V
 of this node, 
0
<= V <= 9.


Given a list of 
ascending
 three-digits integers representing a binary with the depth smaller
than 5. You need to return the sum of all paths from the root towards the leaves.

Example 1:

Input: [113, 215, 221]
Output: 12
Explanation:
The tree that the list represents is:
3
/ \
5   1

The path sum is (3 + 5) + (3 + 1) = 12.


Example 2:

Input: [113, 221]
Output: 4
Explanation:
The tree that the list represents is:
3
\
1

The path sum is (3 + 1) = 4.

解答:

How do we solve problem like this if we were given a normal tree? Yes, traverse it, keep a root to leaf running sum. If we see a leaf node (node.left == null && node.right == null), we add the running sum to the final result.

Now each tree node is represented by a number. 1st digits is the 
level
, 2nd is the 
position
 in
that 
level
 (note that it starts from 
1
instead
of 
0
). 3rd digit is the value. We need to find a way to traverse this 
tree
 and
get the sum.

The idea is, we can form a 
tree
 using a HashMap. The 
key
 is
first two digits which marks the position of a node in the tree. The 
value
is value of
that node. Thus, we can easily find a node's left and right children using math.

Formula: For node 
xy?
 its left child is 
(x+1)(y*2-1)?
 and
right child is 
(x+1)(y*2)?


Given above HashMap and formula, we can traverse the 
tree
. Problem is solved!
class Solution {
int sum = 0;
Map<Integer, Integer> tree = new HashMap<>();

public int pathSum(int[] nums) {
if (nums == null || nums.length == 0) return 0;

for (int num : nums) {
int key = num / 10;
int value = num % 10;
tree.put(key, value);
}

traverse(nums[0] / 10, 0);

return sum;
}

private void traverse(int root, int preSum) {
int level = root / 10;
int pos = root % 10;
int left = (level + 1) * 10 + pos * 2 - 1;
int right = (level + 1) * 10 + pos * 2;

int curSum = preSum + tree.get(root);

if (!tree.containsKey(left) && !tree.containsKey(right)) {
sum += curSum;
return;
}

if (tree.containsKey(left)) traverse(left, curSum);
if (tree.containsKey(right)) traverse(right, curSum);
}
}

另一个解答(没有用HashMap):

0
0       1
0   1     2   3
0 1  2 3   4 5  6 7


Regardless whether these nodes exist:

the position of left child is always 
parent_pos * 2
;

the position of right child is always
parent_pos * 2 + 1
;

the position of parent is always 
child_pos / 2
;

Solution C++ Array
class Solution {
public:
int pathSum(vector<int>& nums) {
int m[5][8] = {};
for (int n : nums) {
int i = n / 100; // i is 1 based index;
int j = (n % 100) / 10 - 1; // j used 0 based index;
int v = n % 10;
m[i][j] = m[i - 1][j / 2] + v;
}

int sum = 0;
for (int i = 1; i < 5; i++) {
for (int j = 0; j < 8; j++) {
if (i == 4 || m[i][j] && !m[i + 1][j * 2] && !m[i + 1][j * 2 + 1]){
sum += m[i][j];
}
}
}
return sum;
}
};


Solution C++ map

If we use map, we don't need to do the boundary check at little extra cost of memory.
class Solution {
public:
int pathSum(vector<int>& nums) {
map<int, map<int, int>> m;
for (int n : nums) {
int i = n / 100 - 1; // i is 0 based index;
int j = (n % 100) / 10 - 1; // j used 0 based index;
int v = n % 10;
m[i][j] = m[i - 1][j / 2] + v;
}

int sum = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 8; j++) {
sum += m[i][j] && !m[i + 1][j * 2] && !m[i + 1][j * 2 + 1] ? m[i][j] : 0;
}
}
return sum;
}
};


Solution C++ - queue
class Solution {
public:
int pathSum(vector<int>& nums) {
if (nums.empty()) return 0;
int sum = 0;
queue<info> q;
info dummy(0);
info* p = &dummy; // parent start with dummy info, root have no real parent;
for (int n : nums) {
info c(n); // child;
while (!p->isparent(c) && !q.empty()) {
sum += p->leaf ? p->v : 0;
p = &q.front();
q.pop();
}
p->leaf = false;
c.v += p->v;
q.push(c);
}
while (!q.empty()) {
sum += q.front().v;
q.pop();
}
return sum;
}
private:
struct info {
int i, j, v;
bool leaf;
info(int n) : i(n / 100 - 1), j((n % 100) / 10 - 1), v(n % 10), leaf(true) {};
bool isparent(info other) { return i == other.i - 1 && j == other.j / 2;};
};
};


Solution Java
class Solution {
public int pathSum(int[] nums) {
int[][] m = new int[5][8];
for (int n : nums) {
int i = n / 100; // i is 1 based index;
int j = (n % 100) / 10 - 1; // j used 0 based index;
int v = n % 10;
m[i][j] = m[i - 1][j / 2] + v;
}

int sum = 0;
for (int i = 1; i < 5; i++) {
for (int j = 0; j < 8; j++) {
if (i == 4 || m[i][j] != 0 && m[i + 1][j * 2] == 0 && m[i + 1][j * 2 + 1] == 0){
sum += m[i][j];
}
}
}
return sum;
}
}


667. Beautiful Arrangement II

Given two integers 
n
 and 
k
,
you need to construct a list which contains 
n
 different positive integers ranging from 
1
 to 
n
 and
obeys the following requirement: 

Suppose this list is [a1, a2, a3,
... , an], then the list [|a1 -
a2|, |a2 - a3|,
|a3 - a4|, ... , |an-1 -
an|] has exactly 
k
 distinct
integers.

If there are multiple answers, print any of them.

Example 1:

Input: n = 3, k = 1
Output: [1, 2, 3]
Explanation: The [1, 2, 3] has three different positive integers ranging from 1 to 3, and the [1, 1] has exactly 1 distinct integer: 1.


Example 2:

Input: n = 3, k = 2
Output: [1, 3, 2]
Explanation: The [1, 3, 2] has three different positive integers ranging from 1 to 3, and the [2, 1] has exactly 2 distinct integers: 1 and 2.


解答:

if you have 
n
 number, the maximum 
k
 can
be 
n - 1
;

if 
n
 is 9, max 
k
 is
8.

This can be done by picking numbers interleavingly from head and tail,
// start from i = 1, j = n;
// i++, j--, i++, j--, i++, j--

1   2   3   4   5
9   8   7   6
out: 1 9 2 8 3 7 6 4 5
dif:  8 7 6 5 4 3 2 1


This is a case where 
k
 is exactly 
n
- 1


When k is less than that, simply lay out the rest 
(i, j)
 in incremental

order(all diff is 1). Say if k is 5:
i++, j--, i++, j--, i++, i++, i++ ...
1   9   2   8    3 4 5 6 7
8   7   6   5    1 1 1 1


C++
class Solution {
public:
vector<int> constructArray(int n, int k) {
vector<int> res;
for (int i = 1, j = n; i <= j; ) {
if (k > 1) {
res.push_back(k-- % 2 ? i++ : j--);
}
else {
res.push_back(k % 2 ? i++ : j--);
}
}
return res;
}

};


C++ Compact
class Solution {
public:
vector<int> constructArray(int n, int k) {
vector<int> res;
for (int i = 1, j = n; i <= j; )
res.push_back(k > 1 ? (k-- % 2 ? i++ : j--) : (k % 2 ? i++ : j--));
return res;
}
};


Java
class Solution {
public int[] constructArray(int n, int k) {
int[] res = new int
;
for (int i = 0, l = 1, r = n; l <= r; i++)
res[i] = k > 1 ? (k-- % 2 != 0 ? l++ : r--) : (k % 2 != 0? l++ : r--);
return res;
}
}

另解:

The requirement of k distinct distance can be achieved from 1, 2, ..., k+1 (<= n), by the following strategy:
1, k+1, 2, k, 3, k-1 ...;
The distance of this sequence is k, k-1, k-2, ..., 2, 1


Then append the remaining numbers to the list.
class Solution {
public:
vector<int> constructArray(int n, int k) {
int l = 1, r = k+1;
vector<int> ans;
while (l <= r) {
ans.push_back(l++);
if (l <= r) ans.push_back(r--);
}
for (int i = k+2; i <= n; i++)
ans.push_back(i);
return ans;
}
};



668. Kth largest Number in Multiplication Table

Nearly every one have used the Multiplication Table. But could you find out the 
k-th
 largest
number quickly from the multiplication table?

Given the height 
m
 and the length 
n
 of
m * n
 Multiplication Table, and a positive integer 
k
,
you need to return the 
k-th
 largest number in this table.

Example 1:

Input: m = 3, n = 3, k = 5
Output:
Explanation:
The Multiplication Table:
1	2	3
2	4	6
3	6	9

The 5-th largest number is 3 (1, 2, 2, 3, 3).


Example 2:

Input: m = 2, n = 3, k = 6
Output:
Explanation:
The Multiplication Table:
1	2	3
2	4	6

The 6-th largest number is 6 (1, 2, 2, 3, 4, 6).


Note:

The 
m
 and 
n
 will
be in the range [1, 30000].
The 
k
 will be in the range [1, m * n]

解答:

Binary Search:

class Solution {
public int findKthNumber(int m, int n, int k) {
int low = 1 , high = m * n + 1;

while (low < high) {
int mid = low + (high - low) / 2;
int c = count(mid, m, n);
if (c >= k) high = mid;
else low = mid + 1;
}

return high;
}

private int count(int v, int m, int n) {
int count = 0;
for (int i = 1; i <= m; i++) {
int temp = Math.min(v / i , n);
count += temp;
}
return count;
}
}

然后有人说这道题抄了codeforces:

This exact problem is found on the Codeforces OJ on this link:

http://codeforces.com/contest/448/problem/D

Its solution is also fully written on stack overflow on this link:
https://stackoverflow.com/questions/33464901/using-binary-search-to-find-k-th-largest-number-in-nm-multiplication-table

I found several people who blindly copied that code and got AC!. The reason I know this problem was on Stackoverflow was because Iwas the one who asked that question in 2015!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: