-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2351. First Letter to Appear Twice
335 lines (261 loc) · 16 KB
/
2351. First Letter to Appear Twice
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
class Solution {
public:
char repeatedCharacter(string s) {
unordered_set<char> tracker;
// for(int i = 0; i < s.size(); i++)
// {
// if(tracker.count(s[i]))
// {
// return s[i];
// }
// tracker.insert(s[i]);
// }
// return ' '; <<<<<<<<<<<<<<<<--------------------------
// ==============================
int i;
for(i = 0; i < s.size(); i++)
{
if(tracker.count(s[i]))
{
break;
}
tracker.insert(s[i]);
}
return s[i];
// ==============================
// for (char c : s)
// {
// if (tracker.count(c))
// {
// return c;
// }
// tracker.insert(c);
// }
// return '\0'; <<<<<<<<<<<<-----------------------
}
};
ExtrAA
//set:
// 1. unordered_set
// Definition: unordered_set is a collection of unique elements. Each element is stored only once, without any association to other values.
// Usage: Primarily used when you need to check for the presence or absence of elements (e.g., checking if an item is in a collection) without
//needing to store any additional information about each element.
// Key Characteristics:
// Only stores keys (no associated values).
// Does not allow duplicate entries.
// Provides O(1) average-time complexity for insertion, deletion, and lookup.
Using unordered_set would not work because:
1. unordered_set only stores keys (characters), not values (frequency counts).
2. You cannot associate a count with each character using unordered_set.
=================================================================================================================================
Let's go through the code execution step-by-step with the input `"abccbaacz"` and see where it identifies the repeated character.
### Code Execution Walkthrough
The code uses an `unordered_set` called `seen` to keep track of characters that have already been encountered. It checks each character in the string in order and returns the first character that is found
in `seen`, which would indicate it has been seen before (i.e., it’s a repeat).
Input:
```plaintext
s = "abccbaacz"
```
### Step-by-Step Execution
1. **Initialize `seen` as an empty set**.
2. Start iterating over each character in `s`:
- **Iteration 1:** `c = 'a'`
- `'a'` is not in `seen`, so we add it to `seen`.
- `seen = {'a'}`
- **Iteration 2:** `c = 'b'`
- `'b'` is not in `seen`, so we add it to `seen`.
- `seen = {'a', 'b'}`
- **Iteration 3:** `c = 'c'`
- `'c'` is not in `seen`, so we add it to `seen`.
- `seen = {'a', 'b', 'c'}`
- **Iteration 4:** `c = 'c'`
- `'c'` is already in `seen`, indicating it’s the first repeated character.
- The code returns `'c'` and exits.
### Summary
The code will correctly return `'c'` as soon as it encounters it a second time, so the output is indeed `'c'`. There is no need to continue further, as the first repeated character has been found.
### Explanation of Output
For the given input, the expected output is indeed `'c'`, and the code works as intended to provide this result. If the code returns `'a'` in any situation, it might be due to incorrect ordering or a
misunderstanding in prior tests, as this version of the code accurately finds the first repeated character in sequence.
====================================================================================================================================================================================================================
Certainly! To visualize how the `unordered_set<char> seen` changes throughout each iteration, we can represent it in a table-like format, similar to an Excel sheet.
Let's create a table where:
- Each row corresponds to an iteration.
- We show the current character being processed, whether it’s already in the set (`seen`), and the state of `seen` after each iteration.
### Table Representation
| Iteration | Current Character (`c`) | Already in `seen`? | Action Taken | `seen` After Iteration |
|-----------|--------------------------|---------------------|--------------------------------------|-------------------------|
| 1 | 'a' | No | Add `'a'` to `seen` | { 'a' } |
| 2 | 'b' | No | Add `'b'` to `seen` | { 'a', 'b' } |
| 3 | 'c' | No | Add `'c'` to `seen` | { 'a', 'b', 'c' } |
| 4 | 'c' | Yes | Return `'c'` as the first repeated character | N/A |
### Explanation
1. **Iteration 1**: We start with `'a'`, which isn’t in `seen`, so we add it.
2. **Iteration 2**: We move to `'b'`, which also isn’t in `seen`, so we add it.
3. **Iteration 3**: Next is `'c'`, which is also new, so we add it.
4. **Iteration 4**: When we encounter `'c'` again, it’s already in `seen`, indicating it’s the first repeated character. The code returns `'c'` immediately and stops further processing.
Using this table approach, you can easily track the contents of `seen` and see the exact point at which the function identifies the first repeated character. Let me know if you need this
exported as an Excel file!
====================================================================================================================================================================================================================
Q) explain how .insert(c) is used and also show its documentation as to how it is used?
ANS:
In C++, the `.insert(c)` function is used with containers like `unordered_set` to add an element (in this case, the character `c`) to the set. Here’s an explanation of how it works,
specifically for `unordered_set`, and what the official documentation says about it.
### Explanation of `.insert(c)` in `unordered_set`
1. **Purpose**: `.insert(c)` attempts to insert the element `c` into the set.
2. **Behavior in Sets**: Sets, by definition, store unique elements. If the element already exists in the set, `.insert(c)` does not add it again.
3. **Return Value**: `.insert(c)` returns a pair:
- The first value in the pair is an iterator pointing to the element.
- The second value is a boolean that indicates whether the insertion took place:
- `true` if the element was inserted (it was not already in the set).
- `false` if the element was already present in the set.
### How It’s Used in Your Code
In the code snippet you provided:
```cpp
seen.insert(c);
```
This line is used to add the character `c` to the `unordered_set<char> seen`. Since `seen` only stores unique values, if `c` is already in `seen`, `.insert(c)` won’t add it again.
This is why the code can reliably check for repeats: once a character is added, trying to insert it again will result in a `false` value in the returned pair.
### Example of `.insert(c)`
Here’s a quick example illustrating how `.insert(c)` behaves:
```cpp
#include <unordered_set>
#include <iostream>
int main() {
std::unordered_set<char> mySet;
auto result1 = mySet.insert('a'); // Inserts 'a', as it is not in the set
std::cout << "Inserted 'a': " << result1.second << std::endl; // Outputs: 1 (true)
auto result2 = mySet.insert('a'); // Tries to insert 'a' again
std::cout << "Inserted 'a' again: " << result2.second << std::endl; // Outputs: 0 (false)
return 0;
}
```
### Documentation Reference
According to the [C++ documentation](https://en.cppreference.com/w/cpp/container/unordered_set/insert), here’s a brief description of `.insert` for `unordered_set`:
- **Prototype**:
```cpp
std::pair<iterator, bool> insert( const value_type& value );
```
- **Parameters**: `value` is the element you want to add (here, `c`).
- **Return Value**: A pair, where:
- `iterator` points to the position of the element in the set.
- `bool` is `true` if the insertion happened, or `false` if the element was already in the set.
This function is efficient for checking and inserting elements when you want to avoid duplicates, which makes it perfect for your repeated character-checking code!
====================================================================================================================================================================================================================
Q) for (char c : s)
{
}
explain this for loop and its documentation for use.
ANS:
The `for (char c : s)` loop is an example of a **range-based for loop** introduced in C++11. It allows you to iterate through all the elements of a container
(like a string, vector, array, etc.) directly without having to manually manage an index.
### Breakdown of `for (char c : s)`:
- **`char c`**: This declares a variable `c` of type `char` that will hold each element of the container `s` as the loop iterates.
- **`s`**: This is the container being iterated over. In this case, `s` is a string, so `c` will take the value of each character in the string during each iteration.
### What Happens in Each Iteration?
- The loop will automatically go through each character of the string `s` in sequence. On the first iteration, `c` will be the first character of `s`, on the second iteration,
`c` will be the second character, and so on, until all characters in `s` are processed.
- After the loop finishes, it will automatically exit, and control will pass to the next line of code following the loop.
### Example of Range-Based For Loop
```cpp
#include <iostream>
#include <string>
int main() {
std::string s = "hello";
// Iterating through the string using range-based for loop
for (char c : s) {
std::cout << c << " "; // Output: h e l l o
}
return 0;
}
```
In this example, `c` takes the value of each character in the string `s`, one by one, and prints it out.
### Key Points:
1. **Automatic Type Deduction**: You can also use `auto` instead of explicitly specifying the type:
```cpp
for (auto c : s) {
// This is equivalent to `for (char c : s)`
}
```
This allows you to avoid explicitly stating the type, which is useful if you're iterating over different types of containers.
2. **Read-Only Access**: In the example `for (char c : s)`, `c` is a copy of each element in the container `s`. If you want to modify the elements of `s` directly inside the loop, you can use a reference:
```cpp
for (char& c : s) {
c = toupper(c); // Converts each character in the string to uppercase
}
```
3. **Const Reference for Efficiency**: If you don’t intend to modify the elements, it’s often more efficient to use a `const` reference, especially for larger objects:
```cpp
for (const char& c : s) {
// `c` is a reference to each character (read-only)
}
```
### Documentation Reference
From [cppreference](https://en.cppreference.com/w/cpp/language/range-for):
- **Syntax**:
```cpp
for (declaration : range) statement
```
where:
- **`declaration`**: a variable that will hold each element from the range in every iteration.
- **`range`**: any object that supports iteration (e.g., an array, string, vector, etc.). For a string, this is a sequence of characters.
### Advantages:
- **Simpler syntax**: No need for manual index management (`i < s.size()` or `i++`).
- **Readability**: It’s easier to understand, especially for containers with more complex structures.
- **Safety**: There’s no risk of going out of bounds, as the loop automatically stops at the end of the container.
In summary, the `for (char c : s)` loop is a simple, readable, and efficient way to iterate through the elements of a container, such as a string, and allows direct access to each
element without needing to manage an index manually.
====================================================================================================================================================================================================================
Q)for(int i = 0; i < s.size(); i++)
{
}
VS
for (char c : s) {
}
which is better and why?
ANS:
Both `for (int i = 0; i < s.size(); i++)` and `for (char c : s)` are valid ways to iterate over a string or other containers in C++, but each has its own strengths and use cases. Let’s break down the
differences and see which one is "better" depending on the scenario.
### 1. **`for (int i = 0; i < s.size(); i++)`**
This is the **traditional for loop** using an index `i` to access each element in the container `s`.
#### Pros:
- **Control over indices**: If you need the index for some reason (e.g., accessing elements by index, modifying elements at a specific index, or keeping track of the position within the container),
this loop is necessary.
- **Flexibility**: You can manipulate `i` in more complex ways (e.g., skipping every other element, iterating in reverse order, etc.).
#### Cons:
- **More verbose**: You have to manually manage the loop variable (`i`), which introduces a bit more complexity and potential for errors, such as off-by-one errors or issues with bounds.
- **Less readable**: In simple cases where you don't need the index, using an index makes the code longer and harder to read.
### Example:
```cpp
for (int i = 0; i < s.size(); i++) {
cout << s[i]; // Access element by index
}
```
### 2. **`for (char c : s)`**
This is a **range-based for loop**, which is available starting from C++11. It automatically iterates over the elements in the container without needing to explicitly manage an index.
#### Pros:
- **Simpler and more readable**: The range-based `for` loop is more concise and eliminates the need to manually manage an index. It is easier to read and understand when you just need to process each element.
- **Avoids indexing errors**: Since there’s no need to worry about the index, you avoid common mistakes like out-of-bounds access or incorrect indexing.
- **No need for `s.size()`**: You don’t need to calculate the size of the string or container explicitly. The loop will just iterate through each element directly.
#### Cons:
- **Less control over the index**: If you need to know the index or position of the element in the container, you won’t have access to it in the range-based loop.
- **Limited to reading**: In its basic form, it’s best used for read-only access. If you need to modify the container elements, you’d need to use a reference (`char& c` instead of `char c`).
### Example:
```cpp
for (char c : s) {
cout << c; // Access element directly
}
```
### Which One is Better?
- **Use `for (int i = 0; i < s.size(); i++)` when:**
- You **need the index** of the elements in the container (e.g., accessing other related elements by index).
- You need to **modify elements** using the index (though this can also be done with references in a range-based loop).
- You need **more control over the loop** (e.g., iterating in reverse, skipping elements, or doing more complex manipulations with the index).
- **Use `for (char c : s)` when:**
- You only need to **process each element** in the container and do not need the index.
- You want **concise, readable code** that avoids potential errors with indexing.
- The loop is **read-only** and you don't need to modify the elements directly (or you can use references for modification).
### Summary:
- **`for (int i = 0; i < s.size(); i++)`** gives you more flexibility, but it’s more verbose and prone to indexing mistakes.
- **`for (char c : s)`** is simpler, easier to read, and safer for cases where you don’t need the index.
In general, **the range-based for loop (`for (char c : s)`) is often preferred** for simplicity, clarity, and safety when you don’t need to work with indices.
However, if you require control over the index or need to modify elements, then the traditional `for` loop may be better.