Skip to content

Commit ce4cb17

Browse files
Add longest increasing subsequence (#19)
requires dynamic allocation
1 parent 3e0eec6 commit ce4cb17

File tree

4 files changed

+77
-0
lines changed

4 files changed

+77
-0
lines changed

build.zig

+7
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ pub fn build(b: *std.Build) void {
9797
.name = "knapsack.zig",
9898
.category = "dynamicProgramming"
9999
});
100+
if (std.mem.eql(u8, op, "dp/longestIncreasingSubsequence"))
101+
build_algorithm(b, .{
102+
.optimize = optimize,
103+
.target = target,
104+
.name = "longestIncreasingSubsequence.zig",
105+
.category = "dynamicProgramming"
106+
});
100107

101108
// Math algorithms
102109
if (std.mem.eql(u8, op, "math/ceil"))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
const std = @import("std");
2+
const print = std.debug.print;
3+
const testing = std.testing;
4+
const ArrayList = std.ArrayList;
5+
6+
// Function that returns the lower bound in O(logn)
7+
pub fn lower_bound(arr: []const i32, key: i32) usize {
8+
var lo: usize = 0;
9+
var hi: usize = arr.len;
10+
11+
while (lo < hi) {
12+
const mid: usize = lo + (hi - lo) / 2;
13+
if (key <= arr[mid]) {
14+
hi = mid;
15+
} else {
16+
lo = mid + 1;
17+
}
18+
}
19+
20+
if (lo < arr.len and arr[lo] < key) {
21+
lo += 1;
22+
}
23+
24+
return lo;
25+
}
26+
27+
// Function that returns the length of the longest increasing subsequence of an array
28+
// Runs in O(nlogn) using the lower bound function
29+
// Arguments:
30+
// arr: the passed array
31+
// allocator: Any std.heap type allocator
32+
pub fn lis(arr: []const i32, allocator: anytype) usize {
33+
var v = ArrayList(i32).init(allocator);
34+
defer v.deinit();
35+
36+
const n = arr.len;
37+
38+
for (0..n) |i| {
39+
const it = lower_bound(v.items, arr[i]);
40+
if (it == v.items.len) {
41+
_ = v.append(arr[i]) catch return 0;
42+
} else {
43+
v.items[it] = arr[i];
44+
}
45+
}
46+
47+
return v.items.len;
48+
}
49+
50+
test "testing longest increasing subsequence function" {
51+
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
52+
defer _ = gpa.deinit();
53+
54+
const v = [4]i32{ 1, 5, 6, 7 };
55+
try testing.expect(lis(&v, gpa.allocator()) == 4);
56+
57+
const v2 = [5]i32{ 1, -1, 5, 6, 7 };
58+
try testing.expect(lis(&v2, gpa.allocator()) == 4);
59+
60+
const v3 = [5]i32{ 1, 2, -1, 0, 1 };
61+
try testing.expect(lis(&v3, gpa.allocator()) == 3);
62+
63+
const v4 = [0]i32{};
64+
try testing.expect(lis(&v4, gpa.allocator()) == 0);
65+
66+
const v5 = [5]i32{ 0, 0, 0, 0, 0 };
67+
try testing.expect(lis(&v5, gpa.allocator()) == 1);
68+
}

runall.cmd

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ rem Data Structures
2525
rem Dynamic Programming
2626
%ZIG_TEST% -Dalgorithm=dp/coinChange %Args%
2727
%ZIG_TEST% -Dalgorithm=dp/knapsack %Args%
28+
%ZIG_TEST% -Dalgorithm=dp/longestIncreasingSubsequence %Args%
2829

2930
rem Sort
3031
%ZIG_TEST% -Dalgorithm=sort/quicksort %Args%

runall.sh

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ $ZIG_TEST -Dalgorithm=ds/lrucache $Args
2525
# Dynamic Programming
2626
$ZIG_TEST -Dalgorithm=dp/coinChange $Args
2727
$ZIG_TEST -Dalgorithm=dp/knapsack $Args
28+
$ZIG_TEST -Dalgorithm=dp/longestIncreasingSubsequence $Args
2829

2930
## Sort
3031
$ZIG_TEST -Dalgorithm=sort/quicksort $Args

0 commit comments

Comments
 (0)