Table of Contents
Slice vs Array
In Go, the syntax for arrays and slices differs, and the presence or absence of a number within the square brackets ([]
) distinguishes them:
Array
- An array has a fixed size, and its size is specified within the square brackets.
- Example:
var arr [5]int
- This creates an array of 5 integers. The size of the array is fixed and cannot be changed.
- Example:
Slice
- A slice does not have a size specified in the square brackets, which allows it to be dynamic.
- Example:
var slice []int
- This creates a slice of integers. Slices are more flexible because they can grow or shrink in size using functions like
append
.
- This creates a slice of integers. Slices are more flexible because they can grow or shrink in size using functions like
- Initialization: make([]int, length, capacity)
- Example, make([]int, 0, 10)
- allocates an underlying array of size 10 and returns a slice of length 0 and capacity 10 that is backed by this underlying array.
- Example:
To summarize:
- Array:
[N]T
whereN
is the length (e.g.,[5]int
) - Slice:
[]T
where the length is not specified (e.g.,[]int
)
Slices in Go are more commonly used due to their flexibility, while arrays are used when you need a fixed-size collection.
Golang Strings Copy
In Go, copying a string can be done in several ways, each with its own space complexity. Here are the most common methods:
1. Using String Slicing
String slicing is the simplest way to create a copy of a string. In Go, slicing a string creates a new string with the same content.
func copyStringSlice(s string) string {
return s[:]
}
- Space Complexity: O(n)
- The space complexity is O(n) because the slice operation creates a new string that occupies the same amount of space as the original string.
2. Using a Loop with String Concatenation
You can manually iterate over each character of the string and concatenate it to a new string. This approach is less efficient in terms of performance but demonstrates manual copying.
func copyStringLoop(s string) string {
var result string
for _, ch := range s {
result += string(ch)
}
return result
}
- Space Complexity: O(n)
- The space complexity is O(n) because each character from the original string is copied into a new string. Additionally, Go strings are immutable, so each concatenation may involve creating a new string.
3. Using fmt.Sprintf
You can use fmt.Sprintf
to create a copy of the string. While it’s not specifically designed for copying strings, it effectively creates a new string.
import "fmt"
func copyStringSprintf(s string) string {
return fmt.Sprintf("%s", s)
}
- Space Complexity: O(n)
- The space complexity is O(n) because the new string will have the same length as the original.
4. Using strings.Builder
strings.Builder
is a more efficient way to build a string if you’re constructing it piece by piece. It can be used to copy a string as well.
// strings.Builder
// will help us to convert the byte buffer into string
// sb.WriteByte is helpful
// sb.String()
// Convert result int array to string
var sb strings.Builder
for _, num := range result {
if !(sb.Len() == 0 && num == 0) { // Skip leading zeros
sb.WriteByte(byte(num + '0'))
}
}
return sb.String()
- Space Complexity: O(n)
- The space complexity is O(n) because
strings.Builder
internally allocates space to store the string, and this space is proportional to the length of the input string.
- The space complexity is O(n) because
5. Using copy
with Byte Slices
You can convert the string to a byte slice, copy it using the copy
function, and then convert it back to a string.
func copyStringWithBytes(s string) string {
b := []byte(s)
copyB := make([]byte, len(b))
copy(copyB, b)
return string(copyB)
}
- Space Complexity: O(n)
- The space complexity is O(n) because the byte slice requires additional memory, and a new string is created from the copied byte slice.
6. Using append
with Byte Slices
This method involves appending the bytes of the string into a new byte slice and converting it back to a string.
func copyStringWithAppend(s string) string {
b := []byte(s)
copyB := append([]byte{}, b...)
return string(copyB)
}
- Space Complexity: O(n)
- The space complexity is O(n) because
append
creates a new byte slice, and the final conversion to a string also requires memory proportional to the length of the string.
- The space complexity is O(n) because
7. Using strings.Clone
(Go 1.18+)
In Go 1.18 and above, strings.Clone
can be used to create a distinct copy of a string:
sub := strings.Clone(inputString[start:end])
This method creates a copy of the string’s underlying data, ensuring it’s not shared with the original string.
Summary of Space Complexity
- String Slicing: O(n)
- Loop with Concatenation: O(n)
fmt.Sprintf
: O(n)strings.Builder
: O(n)copy
with Byte Slices: O(n)append
with Byte Slices: O(n)strings.Clone
: O(n)
All the methods have a space complexity of O(n), where n
is the length of the string. However, they differ in terms of performance and readability, with slicing and using strings.Builder
typically being the most efficient and idiomatic approaches in Go.
Common string – int conversion
Q1. Convert a String into an Integer (int
and int32
)
- Using
strconv.Atoi
: For converting a string toint
import "strconv"
num, err := strconv.Atoi("123")
if err != nil {
fmt.Println("Error:", err)
}
fmt.Println("int:", num) // Output: int: 123
- Using
strconv.ParseInt
: For converting toint32
num, err := strconv.ParseInt("123", 10, 32) // Base 10, bit size 32
if err != nil {
fmt.Println("Error:", err)
}
fmt.Println("int32:", int32(num)) // Output: int32: 123
Q2. Convert a Char into an Integer (int
and int32
)
If you have a single character (rune
or byte
), you can convert it directly:
- Using ASCII manipulation
ch := '7' // Single character
num := ch - '0' // '0' has an ASCII value of 48
fmt.Println("int:", num) // Output: int: 7
For int32
: Same process
num := int32(ch - '0')
fmt.Println("int32:", num) // Output: int32: 7
Q3. Convert an Integer (int
and int32
) into a String
Using strconv.Itoa
: For int
import "strconv"
str := strconv.Itoa(123)
fmt.Println("string:", str) // Output: string: "123"
Using fmt.Sprintf
: For both int
and int32
str := fmt.Sprintf("%d", int32(123))
fmt.Println("string:", str) // Output: string: "123"
Q4. Convert an Integer (int
and int32
) into a Char
Using ASCII manipulation
num := 7
ch := rune(num + '0') // Add '0' to convert to a character
fmt.Printf("char: %c\n", ch) // Output: char: 7
For int32
: Same logic applies
var num int32 = 7
ch := rune(num + '0')
fmt.Printf("char: %c\n", ch) // Output: char: 7
Common String Operations in LeetCode
1. String Reversal
str := "hello"
reversed := ""
for _, ch := range str {
reversed = string(ch) + reversed
}
fmt.Println("Reversed:", reversed) // Output: "olleh"
2. Substring Extraction
str := "leetcode"
fmt.Println("Substring:", str[1:4]) // Output: "eet"
3. Splitting Strings
import "strings"
str := "1,2,3"
parts := strings.Split(str, ",")
fmt.Println("Parts:", parts) // Output: ["1", "2", "3"]
4. Joining Strings
joined := strings.Join([]string{"a", "b", "c"}, ",")
fmt.Println("Joined:", joined) // Output: "a,b,c"
5. Character Count/Frequency
freq := make(map[rune]int)
str := "leetcode"
for _, ch := range str {
freq[ch]++
}
fmt.Println("Frequency:", freq) // Output: map[e:3 l:1 t:1 c:1 o:1 d:1]
6. String Comparison
if "abc" == "abc" {
fmt.Println("Strings are equal")
}
7.String Contains
import "strings"
fmt.Println(strings.Contains("leetcode", "leet")) // Output: true
8. String Indexing
fmt.Println(strings.Index("leetcode", "code")) // Output: 4
9.String Conversion to Bytes and Back
b := []byte("abc")
str := string(b)
fmt.Println("Bytes:", b, "String:", str) // Output: Bytes: [97 98 99] String: abc
10.Palindrome Check
str := "madam"
isPalindrome := true
for i := 0; i < len(str)/2; i++ {
if str[i] != str[len(str)-1-i] {
isPalindrome = false
break
}
}
fmt.Println("Is Palindrome:", isPalindrome) // Output: true
Leave a Reply