From 04cc50e082bca1e476fa1a749c5f932f1c597462 Mon Sep 17 00:00:00 2001 From: Rajas Paranjpe <52586855+ChocolateLoverRaj@users.noreply.github.com> Date: Mon, 27 Apr 2026 23:22:04 -0700 Subject: [PATCH 1/2] Improve Zig Zag conversion Single allocation, no reallocations This takes advantage of each character always being 1 byte, which is guaranteed by the LeetCode constraints. --- src/leetcode/zigzag_conversion.rs | 78 ++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/src/leetcode/zigzag_conversion.rs b/src/leetcode/zigzag_conversion.rs index 847e2ff..8e57fac 100644 --- a/src/leetcode/zigzag_conversion.rs +++ b/src/leetcode/zigzag_conversion.rs @@ -1,32 +1,56 @@ -fn add(u: usize, i: i32) -> Option { - if i.is_negative() { - u.checked_sub(i.wrapping_abs() as u32 as usize) - } else { - u.checked_add(i as usize) +pub fn convert(s: String, num_rows: i32) -> String { + let num_rows = num_rows as usize; + // We know the final len of the string so there will be no reallocation or wasted memory + let mut o = String::with_capacity(s.len()); + let step = match num_rows { + 1 => 1, + num_rows => num_rows * 2 - 2, + }; + // Append the top row + { + let mut i = 0; + loop { + if let Some(c) = s.as_bytes().get(i * step).copied() { + o.push(char::from(c)); + } else { + break; + } + i += 1; + } } -} - -pub fn convert(s: String, n: i32) -> String { - if n == 1 || n as usize >= s.len() { - return s; + // Append middle rows + for row in 1..num_rows - 1 { + let start_0 = row; + let start_1 = num_rows * 2 - 2 - row; + let mut i = 0; + loop { + if let Some(c) = s.as_bytes().get(start_0 + i * step).copied() { + o.push(char::from(c)); + } else { + break; + } + if let Some(c) = s.as_bytes().get(start_1 + i * step).copied() { + o.push(char::from(c)); + } else { + break; + } + i += 1; + } } - - let mut rows = vec![String::new(); n as usize]; - - let mut row_index = 0; - let mut step = 1; - for c in s.chars() { - rows[row_index].push(c); - if row_index == 0 { - step = 1; - } else if row_index == n as usize - 1 { - step = -1; + // Append the last row + if num_rows > 1 { + let start = num_rows - 1; + let mut i = 0; + loop { + if let Some(c) = s.as_bytes().get(start + i * step).copied() { + o.push(char::from(c)); + } else { + break; + } + i += 1; } - - row_index = add(row_index, step).unwrap(); } - - rows.join("") + o } #[cfg(test)] @@ -43,6 +67,8 @@ mod tests { assert_eq!( "PINALSIGYAHRPI".to_string(), convert("PAYPALISHIRING".to_string(), 4) - ) + ); + + assert_eq!("A".to_string(), convert("A".to_string(), 1)); } } From 50610e0f2926273b7ba22134863ed246da737aa2 Mon Sep 17 00:00:00 2001 From: jusexton Date: Wed, 6 May 2026 22:37:43 -0500 Subject: [PATCH 2/2] fix linting --- src/leetcode/zigzag_conversion.rs | 66 ++++++++++++------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/src/leetcode/zigzag_conversion.rs b/src/leetcode/zigzag_conversion.rs index 8e57fac..ac4bf2f 100644 --- a/src/leetcode/zigzag_conversion.rs +++ b/src/leetcode/zigzag_conversion.rs @@ -1,55 +1,41 @@ pub fn convert(s: String, num_rows: i32) -> String { - let num_rows = num_rows as usize; - // We know the final len of the string so there will be no reallocation or wasted memory - let mut o = String::with_capacity(s.len()); - let step = match num_rows { - 1 => 1, - num_rows => num_rows * 2 - 2, - }; - // Append the top row - { + fn append(o: &mut String, bytes: &[u8], start: usize, step: usize) { let mut i = 0; - loop { - if let Some(c) = s.as_bytes().get(i * step).copied() { - o.push(char::from(c)); - } else { - break; - } + while let Some(&c) = bytes.get(start + i * step) { + o.push(c as char); i += 1; } } - // Append middle rows - for row in 1..num_rows - 1 { - let start_0 = row; - let start_1 = num_rows * 2 - 2 - row; + + let num_rows = num_rows as usize; + let bytes = s.as_bytes(); + let step = match num_rows { + 1 => 1, + n => n * 2 - 2, + }; + let mut o = String::with_capacity(s.len()); + + // Top row + append(&mut o, bytes, 0, step); + + // Middle rows + for row in 1..num_rows.saturating_sub(1) { let mut i = 0; - loop { - if let Some(c) = s.as_bytes().get(start_0 + i * step).copied() { - o.push(char::from(c)); - } else { - break; - } - if let Some(c) = s.as_bytes().get(start_1 + i * step).copied() { - o.push(char::from(c)); - } else { - break; + while let Some(&a) = bytes.get(row + i * step) { + o.push(a as char); + match bytes.get((step - row) + i * step).copied() { + Some(b) => o.push(b as char), + None => break, } i += 1; } } - // Append the last row + + // Bottom row if num_rows > 1 { - let start = num_rows - 1; - let mut i = 0; - loop { - if let Some(c) = s.as_bytes().get(start + i * step).copied() { - o.push(char::from(c)); - } else { - break; - } - i += 1; - } + append(&mut o, bytes, num_rows - 1, step); } + o }