Algorithm Problem Sets
Posted on January 1, 2013
Tags: algorithms
1 python vs C++ in CSES
- Use Python
- CSES will TLE python even if the code structure is the same with C++
= list(map(int, input().split()))
a, goal = list(map(int, input().split()))
choice
= [-1 for i in range(goal+1000000)]
DP 0] = 0
DP[= max(choice)
maxj for i in choice:
= 1
DP[i] = 0
k while k <= goal:
for j in choice:
if k+j > goal:
choice.remove(j)pass
if DP[k] >= 0:
if DP[k+j] >= 0:
+j] = min(DP[k+j],DP[k]+1)
DP[kelse:
+ j] = DP[k]+1
DP[k = k + 1
k print(DP[goal])
#include <bits/stdc++.h>
int main(){
int DP[1000100];
[0]=0;
DPfor(int i = 0; i < 1000101; i++){
[i] = -1;
DP}
int TC, goal;
std::vector<int> choice;
("%d %d",&TC,&goal);
scanf// std::cout<< TC<< goal << "\n";
while (TC--){
int tmp;
("%d",&tmp);
scanf.push_back(tmp);
choice}
for(int j : choice){
[j] = 1;
DP}
int k = 0;
while(k < goal){
for(int j : choice){
// std::cout << j;
if (DP[k] >= 0 && k + j <= goal){
if(DP[k+j] >= 0){
[k+j] = std::min(DP[k+j],DP[k]+1);
DP}else{
[k+j]=DP[k]+1;
DP}
}
}
= k+1;
k }
// for(int i = 0; i < 13; i++){
// std::cout << DP[i] << " ";
// }
std::cout <<DP[goal] << "\n";
}
//g++ shit.cpp && ./a.out
2 Documenting some random algorithmic problems:
Describe an algorithm that given a linked list,
if odd returns the middle element,
if even length then return the first of the two middle elements.
- Solve with 2 pointers, state of subproblem isomorphic with size of partition of 1st pointer allowing induction.
- 1st pointer moves 2-spaces
- 1st pointer partitions the list to a subproblem
- 2nd pointer moves 1-space
- 2nd pointer is IH invariant to each subproblem.
2nd pointer represents the solution or midpoint of the list.
- 2nd pointer is IH invariant to each subproblem.
Design recursive procedure that takes n::int and returns ALL n-length lists where all consecutive letters are distinct. Only letters {A,B,C} can be used.
Eg. ‘AB’ ‘AC’ ‘BA’ ‘BC’ ‘CA’ ‘CB’
- IH: For (n-1) assume we have solution::[[str]] containing
list of (n-1)-lists = {‘A..’,‘B..’,‘C..’,…} - For each (n-1)-list in IH check head of the (n-1)-list then build new lists from the 2 letters that do not match the head.
Eg: if ‘A…’ we add B or C to get new combinations {‘BA..’,‘CA..’}
Misconception:
- Why not also check for tail of (n-1)-list?
- combinations would repeat giving us double the solutions.
- Assume {‘A..C’,‘B..A’} \(\in\) IH
- Append to B,C to head ‘A..C’ => {‘BA..C’,‘CA..C’}
- Append to B,C to tail ‘B..A’ => {‘B..AC’,‘B..AB’}
- Notice ‘BA..C’ and ‘B..AC’ are the same
- combinations would repeat giving us double the solutions.
4-pole Hanoi. Given 4 poles A,B,C,D clockwise in a square, you can only move clock wise. Design a method to move n::int disk from A to B.
A–B
| |
D–C
- IH: Assume we can move (n-1) disk to neighboring pairs like (A,B), (B,C) …
- Keypoints
- We can still use IH on the (n-1) disks after moving the largest bottom disk,
since the largest disk does not cause any side effect or reduce degree of freedom.
- We can still use IH on the (n-1) disks after moving the largest bottom disk,
- move top (n-1) disks from A to B. [IH]
- [ A={n}, B={n-1,n-2..}]
- move all (n-1) disks from B to C. [IH]
- [ A={n}, B={} , C={n-1,n-2,…}]
- move all (n-1) disks from C to D. [IH]
- [ A={n}, B={} , C={}, D={n-1,n-2,…}]
- move single largest disk from A to B.
- [ A={}, B={n}, D={n-1,n-2,…}]
- move all (n-1) disks from D to A. [IH]
- [ A={n-1,n-2,…} , B={n} ]
- move all (n-1) disks from A to B. [IH]
- [ B={n,n-1,n-2…} ]
Take Tree T as an input. For every node C, output the shortest path from C to the closest leaf.
3 TwoSum
#Psuedocode
Goal: Return INDEX of nums that sum to target
nums = [2,7,11,15]
hmap = {Value#1stpartialSum |-> Index#2ndpartialSum}
also {Value#2ndpartialSum |-> Index#1stpartialSum}
where Invariant is Value#1stpartialSum + Value#2ndPartialSum = target
let nums = Value#1stpartialSum
enumerate(nums) = {index |-> nums} where i::index, k::Value#1stpartialSum
check k::Value#1stpartialSum in hmap
true => return [hmap(k)::Index#2ndpartialSum, (index of k::Value#1stpartialSum)::Index#1ndpartialSum
false => SET hmap[target - Value#1stpartialSum |-> Index#2ndpartialSum]
class Solution(object):
def twoSum(self, nums, target):
hmap = {}
for Index1stPartial,Value1stPartial in enumerate(nums):
if Value1stPartial in hmap:
Index2ndPartial=hmap[Value1stPartial]
return [Index2ndPartial,Index1stPartial]
Value2ndPartial = target-Value1stPartial
hmap[Value2ndPartial] = Index1stPartial
return []
#Test = Solution().twoSum([2,7,11,15],9)
#print(Test)
func twoSum(nums []int, target int) []int {
:= make(map[int]int)
hmap for Index1stPartial, Value1stPartial := range nums {
if _, exists := hmap[Value1stPartial]; exists {
:= hmap[Value1stPartial]
Index2ndPartial return []int{Index2ndPartial, Index1stPartial}
} else {
:= target - Value1stPartial
Value2ndPartial [Value2ndPartial] = Index1stPartial
hmap}
}
return []int{}
}
2 cases:
Hashmap Miss
Hashmap hit