adjcent integers are not greater than a given number target.
If the array before adjustment is A, the array after adjustment is B, you
should minimize the sum of |A[i]-B[i]|
例子
Given [1,4,2,3] and target=1, one of the solutions is [2,3,2,3], the
adjustment cost is 2 and it's minimal. Return 2.
分析:用DP可解。先找到输入array A的最小值min和最大值max。
然后建一个二维数组cost[i][j],其中0<= i < len(A), 0<= j < max-min+1
递归公式是 cost[i][j] = min(cost[i-1][j-target], ..., cost[i-1][j+target]) + abs(A[j] - (j+min))
python实现如下:
def get_min_cost(A, target):
if len(A) < 2:
return 0
min_val = min(A)
max_val = max(A)
clen = max_val+1-min_val
B = [-1 for i in range(clen)]
table = [B[:] for c in A]
for j in range(clen):
table[0][j] = abs(A[0]-(j+min_val))
for i in range(1, len(A)):
for j in range(clen):
start = max(j-target, 0)
end = min(j+target+1, clen)
table[i][j] = min(table[i-1][start:end]) + abs(A[i]-(j+min_val))
return min(table[-1])
Q2. 有一个长为L的木料需要割开,割的位置在一个数组里A[1...N],从一个地方切开的cost是当前所
切木料的长度,按不同的顺序切割,得到的total cost是不一样的,问怎么切cost最小。
分析:这是一道老题,用DP,递归公式如下:
定义从i位置到j位置(i<j)的木料段的cost是 cost[i][j] = min(cost[i][k]+cost[k][j]) + (A[j]-A[i]),其中k = i+1....j-1 。
Python 实现如下:
def get_min_cost(A, N):
if not A:
return 0
elif len(A) == 1:
return N
A.sort()
A.insert(0, 0)
A.append(N)
cost = {}
for i in range(len(A)):
if(i+1<len(A)): cost[(i,i+1)] = 0
for m in range(2, len(A)):
i = 0
for j in range(m, len(A)):
cost[(i, j)] = N*len(A)
for k in range(i+1, j):
cost[(i, j)] = min(cost[(i, j)], cost[(i,k)] + cost[(k, j)] + (A[j] - A[i]))
i+=1
return cost[(0, len(A)-1)]
Q3. 在一个二维平面,原点(1,1), 跳跃规则(a,b) to (a+b,b) or (a,b+a). 给任意一个坐
标(m,n), 返回从原点到达的最小步数
分析:
使用 辗转相除法,同样的方法还适用于 求两个数的最大公约数,具体参见 http://en.wikipedia.org/wiki/Euclidean_algorithm 。
Python 实现如下:
def find_num_steps(A):
if A[0] <= 0 or A[1] <= 0:
return -1
small_val = min(A[0], A[1])
large_val = max(A[0], A[1])
nsteps = 0
while small_val != 1:
nsteps = large_val//small_val;
temp = small_val
small_val = large_val % small_val
large_val = temp
if small_val == 0: return -1
nsteps += large_val//small_val -1
return nsteps
Q4. 1. You have a number of meetings (with their start and end times). You need
to schedule them using the minimum number of rooms. Return the list of
meetings in every room.
分析:假设每个会议用[start, end]的interval表示,这道题有两个解法:
方法1:用贪心算法,把所有会议按开始时间排序,然后插入房间,如果当前已经在使用的房间能够安排,就插入该会议。否则,就要开新房间。
这个解法的时间复杂度是O(N^2)。
python 实现如下:
def arrangeRoom( A):
A.sort(key = lambda x:x[0])
res = [[A[0]]]
for i in range(1,len(A)):
for j in range(len(res)):
if res[j][-1][-1] <= A[i][0]:
res[j].append(A[i])
break
if j == len(res) - 1:
res.append([A[i]])
return res
方法2:在方法1的基础上还可以优化,把安排的房间按最后会议的结束时间,建个最小堆。每次对于新的会议,只要和堆顶房间比较。如果不冲突,就加入该房间,否则,只能开新房间了。加入后,维护最小堆。时间复杂度是O(N logN),比方法1要好一点。
C++ 实现如下:
struct Interval{
int start;
int end;
Interval(int s, int e) : start(s), end(e) {}
};
class LessStart{
public:
bool operator()(const Interval& a, const Interval& b) const{
return a.start < b.start;
}
};
class GreaterEnd{
public:
bool operator()(const vector<Interval>& a, const vector<Interval>& b) const{
return a.back().end > b.back().end;
}
};
vector<vector<Interval> > arrangeRoom(vector<Interval> meetings){
vector<vector<Interval> > result;
if(meetings.empty()) return result;
sort(meetings.begin(), meetings.end(), LessStart());
result.push_back(vector<Interval>(1, meetings[0]));
GreaterEnd comp;
for(int i=1; i<meetings.size(); ++i){
if(meetings[i].start >= result.front().back().end){
pop_heap(result.begin(), result.end(), comp);
result.back().push_back(meetings[i]);
push_heap(result.begin(), result.end(), comp);
}
else{
result.push_back(vector<Interval>(1, meetings[i]));
push_heap(result.begin(), result.end(), comp);
}
}
return result;
}