I'm trying to solve an "Almost Sorted" challenge in hackerrank the problem is:
Given an array with elements, can you sort this array in ascending order using only one of the following operations?
Swap two elements.
Reverse one sub-segment.
Input Format
The first line contains a single integer, , which indicates the size of the array.
The next line contains integers separated by spaces.
Sample Input #1
2
4 2
Sample Output #1
yes
swap 1 2
Sample Input #2
3
3 1 2
Sample Output #2
no
Sample Input #3
6
1 5 4 3 2 6
Sample Output #3
yes
reverse 2 5
I tried to solve the challenge and my code is working but it seems it's to slow for big arrays.
Kindly asking you to help me to find a better solution for mentioned problem.
Below is my code:
import java.util.*;
public class Solution
{
private static int[] arr;
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int N = in.nextInt();
arr = new int[N];
for (int i = 0; i < N; i++)
{
arr[i] = in.nextInt();
}
if (IsSorted(arr))
{
System.out.println("yes");
return;
}
if(CheckSingleSwap(arr))
return;
if(CheckSingleReverse(arr))
return;
System.out.println("no");
}
private static boolean CheckSingleReverse(int[] arr)
{
int length = arr.length;
int limit = length - 2;
int current = 1;
List<Integer> indexes = new ArrayList<Integer>();
while (current < limit)
{
for (int i = 0; i < length; i++)
{
int temp = current + i;
for (int j = i; j <= temp && temp < length; j++)
{
indexes.add(j);
}
if (IsSorted(ReverseArrayPart(arr, indexes)))
{
System.out.println("yes");
System.out.println("reverse " + (indexes.get(0) + 1) + " " + (indexes.get(indexes.size() - 1) + 1));
return true;
}
indexes.clear();
}
current++;
}
return false;
}
private static int[] ReverseArrayPart(int[] arr, List<Integer> indexes)
{
int[] result = new int[arr.length];
int[] arrayPart = new int[indexes.size()];
int j = 0;
for (int i = 0; i < arr.length; i++)
{
if (indexes.contains(i))
{
arrayPart[j] = arr[i];
j++;
}
result[i] = arr[i];
}
for(int i = 0; i < arrayPart.length / 2; i++)
{
int temp = arrayPart[i];
arrayPart[i] = arrayPart[arrayPart.length - i - 1];
arrayPart[arrayPart.length - i - 1] = temp;
}
j = 0;
for (int i = 0; i < result.length; i++)
{
if (indexes.contains(i))
{
result[i] = arrayPart[j];
j++;
}
}
return result;
}
private static boolean CheckSingleSwap(int[] arr)
{
int count = 0;
int[] B = Arrays.copyOf(arr, arr.length);
Arrays.sort(B);
List<Integer> indexes = new ArrayList<Integer>();
for(int i = 0; i < arr.length; i++)
{
if(arr[i] != B[i])
{
count++;
indexes.add(i+1);
}
}
if(count > 2)
return false;
System.out.println("yes");
System.out.println("swap " + indexes.get(0) + " " + indexes.get(1));
return true;
}
private static boolean IsSorted(int[] arr)
{
int length = arr.length;
for (int i = 0; i < length - 1; i++)
{
if (arr[i] > arr[i + 1])
{
return false;
}
}
return true;
}
}
For the following code, pass in A as the original array and B as the sorted array.
CheckSingleSwap:
Instead of adding the indices to another list, store the first swap you encounter, and keep going; if you find the corresponding other swap, then store it and record the finding; if you find a different swap, exit with false. At the end if you've recorded the finding, print the corresponding indices.
private static boolean CheckSingleSwap(int[] A, int[] B)
{
int L = A.length;
int firstSwap = -1, secondSwap = -1;
for(int i = 0; i < L; i++)
{
if(A[i] != B[i])
{
if (firstSwap == -1)
firstSwap = i;
else if (secondSwap == -1 && A[i] == B[firstSwap] && A[firstSwap] == B[i])
secondSwap = i;
else
return false;
}
}
if (firstSwap != -1 && secondSwap != -1)
{
System.out.println("yes");
System.out.println("swap " + (firstSwap + 1) + " " + (secondSwap + 1));
return true;
}
System.out.println("array is already sorted!");
return false; // or whatever you decide to do; maybe even an exception or enumerated type
}
CheckSingleReverse:
You are doing WAY too much here! You seem to be brute forcing every single possible case (at first glance).
What you can do instead is to find the region where all the numbers are different. If there are more than two of these, or two which are separated by more than one element, then return false immediately.
The reason for the "more than one" thing above is because of odd-number length regions - the middle element would be the same. If you find such two regions, treat them as one. Then you can proceed to find out if the region is reversed.
private static boolean CheckSingleReverse(int[] A, int[] B)
{
// find region
int L = A.length;
int diffStart = -1, diffEnd = -1; boolean mid = false, found = false;
for (int i = 0; i < L; i++)
{
if (A[i] != B[i])
{
if (found)
{
if (i - diffEnd == 2 && !mid)
{
mid = true;
found = false;
diffEnd = -1;
}
else
return false;
}
else if (diffStart == -1)
diffStart = i;
}
else
if (diffStart != -1 && diffEnd == -1)
{
found = true;
diffEnd = i - 1;
}
}
if (diffEnd == -1)
{
if (A[L - 1] != B[L - 1])
diffEnd = L - 1;
else if (!found)
{
System.out.println("array is already sorted!");
return false;
}
}
// find out if it's reversed
int count = (diffEnd - diffStart + 1) / 2;
for (int i = 0; i < count; i++)
{
int oneEnd = diffStart + i, otherEnd = diffEnd - i;
if (!(A[oneEnd] == B[otherEnd] && A[otherEnd] == B[oneEnd]))
return false;
}
System.out.println("yes");
System.out.println("reverse " + (diffStart + 1) + " " + (diffEnd + 1));
return true;
}
Just to give you an idea of the performance boost, on ideone.com, with an array length of 150, the original implementation of CheckSingleReverse took 1.83 seconds, whereas the new one took just 0.1 seconds. With a length of 250, the original actually exceeded the computational time limit (5 seconds), whereas the new one still took just 0.12 seconds.
From this it would seem that your implementation takes exponential time, whereas mine is linear time (ignoring the sorting).
Funnily enough, with an array size of 3 million I'm still getting around 0.26 seconds (ideone's execution time fluctuates a bit as well, probs due to demand)
Related
I have a requirement to create a list of lists where the each list if of length 5 or the sum of the values in the list is <= 10 (whichever happens first). So far I have:
int currentSize = 0;
Boolean size = false;
Boolean length = false;
for (int s : keyListMax) {
if(currentSize >= 10) {
sizeReached = true;
}
if(currentList.size() >= 5) {
lengthReached = true;
}
if(!sizeReached && !lengthReached) {
currentSize += currentList.stream().mapToInt(Integer::intValue).sum();
currentList.add(s);
}
else {
result.add(0, currentList);
currentList.clear();
currentSize = 0;
}
}
System.out.println("Result is: " + result);
But the result is list of empty lists (maybe because of the clear() I’m using?). Also, how can I achieve this using Java 8?
A much easier solution is just to keep a running total of the elements you have added:
int i = 0;
while (i < keyListMax.size()) {
int start = i;
int sum = 0;
do {
sum += keyListMax.get(i);
++i;
} while (i < keyListMax.size()
&& i < start + 5
&& sum + keyListMax.get(i) <= 10);
result.add(0, new ArrayList<>(keyListMax.subList(start, i)));
}
Question is : The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P A H N
A P L S I I G
Y I R
And then read line by line: "PAHNAPLSIIGYIR"
I have written below code, appearantly it works fine, but I might miss some corner cases. Could you help me to find all the corner cases for this question on my answer?
public static String zigZagConversion(String s , int rowNum){
if (s == null){
throw new IllegalArgumentException();
}
if (rowNum == 1){
return s;
}
StringBuilder str = new StringBuilder();
int step = 2 * rowNum - 2 ;
for (int i = 0 ; i < rowNum ; i++){
if( i == 0 || i == rowNum -1){
for (int j = i ; j < s.length() ; j +=step){
str.append(s.charAt(j));
}
}
else{
int step2 = 2* (rowNum - i - 1);
int step3 = step - step2;
int k = i;
boolean flag = true;
while (k < s.length()){
str.append(s.charAt(k));
if(flag){
k += step2;
flag = false;
}
else{
k +=step3;
flag = false;
}
}
}
}
return str.toString();
}
It gives incorrect output for "PAYPALISHIRING", 4
P I N
A L S I G
Y A H R
P I
So the correct answer should be PINALSIGYAHRPI.
But your program gives PINALIGYAIHRNPI:
an "S" is missing, one extra "I" and one extra "N".
Your revised version is still incorrect, it gives PINALSIIGYAHNPI.
The problem is in the while loop in the middle.
You need to alternate the step counting,
setting the flag on and off.
Your mistake was to only set it off once, and never back on again.
str.append(s.charAt(k));
if (flag) {
k += step2;
flag = false;
} else {
k += step3;
flag = true;
}
With this correction, I believe your solution is correct. (I also added a minor improvement there, extracting the common str.append(s.charAt(k)); from the if-else branches.
My solution on leetcode forum:
https://leetcode.com/problems/zigzag-conversion/discuss/549451/Java-Solution-O(n)-with-algorithm
The mathematic algorithm for zigzag is:
originalDiff = numRows * 2 - 2;
If -> 'currRow' equals First or last lines
use the originalDiff (numRows * 2 - 2)
Else ->
For each new line:
upperDiff += 2,
lowerDiff -=2
Examples:
numRows =2 -> originalDiff = 2
PYAIHRN
APLSIIG
3 -> 4
P A H N
A P L S I I G
Y I R
numRows = 4 -> originalDiff = 6
P I N
A L S I G
Y A H R
P I
numRows = 5 -> originalDiff = 8
P H
A SI
Y I R
P L I G
A N
*/
My solution:
class Solution {
public String convert(String s, int numRows) {
if(numRows == 1) {
return s;
}
String newString = "";
int originalDiff = numRows * 2 - 2;
int diff = originalDiff;
int upperDiff = 0;
boolean isGoingDown = true;
int currIndex = 0;
int currRow = 0;
int startingIndex = 0;
for(int i = 0; i < s.length(); i++) {
System.out.println(currIndex);
newString += s.charAt(currIndex);
if(currRow == 0 || currRow == numRows - 1) {
currIndex += originalDiff;
} else {
if(isGoingDown) {
currIndex += diff;
isGoingDown = !isGoingDown;
} else {
currIndex += upperDiff;
isGoingDown = !isGoingDown;
}
}
if(currIndex >= s.length()) {
currRow++;
diff -= 2;
upperDiff += 2;
currIndex = currRow;
isGoingDown = true;
}
if(currRow == numRows) {
i = s.length();
}
}
return newString;
}
}
Zigzag conversion from leetcode in Javascript
Solution
const zigzag = (str, num) => {
if (num === 1) {
return str;
}
let check = true;
let result = [];
let i = 0;
while (i < str.length) {
result.push([]);
let j = 0;
while (j < num) {
if (check){
result[result.length-1].push(str[i]);
i++;
} else {
if (j == 0) {
result[result.length-1].push(null);
} else if (j === num-1) {
result[result.length-1].unshift(null);
} else {
result[result.length-1].unshift(str[i]);
i++;
}
}
j++;
}
check = !check;
}
let zigzag = [];
for (let k = 0; k < num; k++){
for(let l = 0; l < result.length; l++) {
zigzag.push(result[l][k]);
}
}
return zigzag.join("");
}
Example Input
zigzag("ABCD", 3)
Output
ABDC
Run
https://repl.it/#VinitKhandelwal/zigzag-conversion-javascript
Using HashMap
public String convert(String s, int numRows) {
if (numRows == 1){
return s;
}
StringBuilder result = new StringBuilder();
Map<Integer, StringBuilder> map = new HashMap<>();
for (int i = 0; i < numRows; i++) {
map.put(i,new StringBuilder());
}
int it = 0;
boolean flip = true;
for (int i = 0; i < s.length(); i++) {
if (flip) {
if(it<s.length()){
map.get(it).append(s.charAt(i));
it++;
}
} else {
map.get(it).append(s.charAt(i));
it--;
}
if (it + 1 == numRows || it == 0)
flip = !flip;
}
for (Map.Entry entry: map.entrySet()) {
result.append(entry.getValue());
}
return result.toString();
}
My Solution is traversing the string in the same way it is said in the problem, it is better to make string array of size numrows and the rest is storing the string character as it is in the logic,
you can keep the index and when that index is 0 i.e at the starting then we have to go till the end of the row and then except for first and last row, every array will have diagonal element.
So after traversing till the end then assign index = numrows - 2 and save in the respective array string and decrease and do the same till index >0 and then again traverse till the end row, do this and when we reach the end of the string then break from the loop.
and then concate all the string of string array in a new res string.
class Solution {
public String convert(String s, int n) {
if(n==1 || n>=s.length())
return s;
String[] a = new String[n]; //string array
int ind=0; // index for the string array
boolean flag=true;
int cnt=0; //to keep the counter till where we have traversed the string
while(true && flag)
{
if(ind==0)
{
for(int i=0;i<n;i++)
{
a[i] += s.charAt(cnt);
cnt++;
if(cnt==s.length())
{
flag=false;
break;
}
} // here it has reached the end so we assign here
ind = n-2;
}
else if(ind>0 && ind<n && flag)
{
a[ind] += s.charAt(cnt);
cnt++;
if(cnt==s.length())
{
flag=false;
break;
}
ind--; // to move diagonally up
}
}
String res = new String("");
for(int i=0;i<a.length;i++)
{
// System.out.println(a[i].substring(4));
res += a[i].substring(4);
}
return res;
}
}
Following is the simple solution.
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows <= 1:
return s
res = ""
p = numRows * 2 - 2
temp = p
for i in range(0,numRows):
index = i
flag = 0
while index < len(s):
res = res + s[index]
if i == 0 or i == numRows-1:
index = index + p
else:
if flag == 0:
index = index + temp
flag = 1
else:
index = index + p-temp
flag = 0
temp = temp - 2
return res
zigzag-conversion Complete JavaScript-based solution
Created an Array of an array of row lengths. The main motive is to arrange characters in 2D array form and concat string row-wise.
var convert = function(s, numRows) {
let array =[],c=0,str='';
for(let row =0; row<numRows ; row++) {
array[row] = new Array();
}
while(c < s.length) {
for(let row =0; row<numRows ; row++) {
if((row+1)%numRows ==0) {
array[row].push(s[c]);
c++;
break;
} else {
array[row].push(s[c]);
c++;
}
}
for(let rr = numRows-2 ; rr>0;rr--) {
array[rr].push(s[c]);
c++;
}
}
for(let row =0; row<numRows ; row++) {
for(let i=0;i<array[row].length;i++){
if(array[row][i]){
str+=array[row][i]
}
}
}
return str
};
convert("PAYPALISHIRING",3)
This code supposed to output the longest run on which a character in a string has a consecutive runs of itself. Though the problem is that it outputs: 8 (which should be 5 instead). I just would like to ask what seems to be the problem regarding this code.
public class Sample {
public static void main(String[] args) {
String setofletters = "aaakkcccccczz"; /* 15 */
int output = runLongestIndex(setofletters);
System.out.println("Longest run that first appeared in index:" + output);
}
public static int runLongestIndex(String setofletters) {
int ctr = 0;
int ctrstor = 0;
int ii = 0;
int output = 0;
// loops until the last character in the string
for (int i = 0; i < setofletters.length() - 1; i++) {
// checks if the letter is the same to the next
if (setofletters.charAt(i) == setofletters.charAt(i++)) {
ctr++;
ii = i++;
// loops until the letter in the index is no longer equal
while (setofletters.charAt(i) == setofletters.charAt(ii)) {
ii++;
ctr++;
}
if (ctr > ctrstor) {
output = i;
}
// storing purposes
ctrstor = ctr;
}
// resets the counter
ctr = 0;
}
return output;
}
}
UPDATE Sorry, I misunderstood your question a bit, you need to make the following changes in your code to make it work.(lines with comments)
public static int runLongestIndex(String setofletters){
int ctr = 1; // every character is repeated at least once, so you should initialize it to 1, not 0
int ctrstor = 0;
int ii = 0;
int output = 0;
for (int i = 0; i < setofletters.length() - 1; i++) {
if (i < setofletters.length() - 1 && setofletters.charAt(i) == setofletters.charAt(i+1)) { // i++ is not same as i+1
ctr++;
ii = i+1; // i++ is not same as i+1
while (setofletters.charAt(i) == setofletters.charAt(ii)) {
ii++;
ctr++;
}
if (ctr > ctrstor) {
output = i;
}
ctrstor = ctr;
}
ctr = 1; // for the same reason I mentioned above
}
return output;
}
EDIT : the easiest way to write your code is :
public static int runLongestIndex(String setofletters){
int ctr = 1;
int output = 0;
int j=0;
for(int i=0; i<setofletters.length()-1;i++){
j=i;
while(i <setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){
i++;
ctr++;
}
if(ctr>output){
output=j;
}
ctr = 1;
}
return output;
}
Why are you assigning i to output? You should assign ctr to output.
change
if(ctr>ctrstor){
output=i;
}
to
if(ctr>ctrstor){
output=ctr;
}
and also I think you should change
if(setofletters.charAt(i)==setofletters.charAt(i++))
to
if(i<setofletters.length()-1 && setofletters.charAt(i)==setofletters.charAt(i+1)){
and you should intialize ctr to 1 but not 0 because every character is repeated at least once.
I'll give you a Scala implementation for that problem.
Here it is the automatic test (in BDD style with ScalaTest)
import org.scalatest._
class RichStringSpec extends FlatSpec with MustMatchers {
"A rich string" should "find the longest run of consecutive characters" in {
import Example._
"abceedd".longestRun mustBe Set("ee", "dd")
"aeebceeedd".longestRun mustBe Set("eee")
"aaaaaaa".longestRun mustBe Set("aaaaaaa")
"abcdefgh".longestRun mustBe empty
}
}
Following is the imperative style implementation, with nested loops and mutable variables as you would normally choose to do in Java or C++:
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
val chunks = mutable.Set.empty[String]
val ilen = string.length
var gmax = 0
for ((ch, curr) <- string.zipWithIndex) {
val chunk = mutable.ListBuffer(ch)
var next = curr + 1
while (next < ilen && string(next) == ch) {
chunk += string(next)
next = next + 1
}
gmax = chunk.length max gmax
if (gmax > 1) chunks += chunk.mkString
}
chunks.toSet.filter( _.length == gmax )
}
}
}
Following is a functional-style implementation, hence no variables, no loops but tail recursion with result accumulators and pattern matching to compare each character with the next one (Crazy! Isn't it?):
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
def recurse(chars: String, chunk: mutable.ListBuffer[Char], chunks: mutable.Set[String]): Set[String] = {
chars.toList match {
case List(x, y, _*) if (x == y) =>
recurse(
chars.tail,
if (chunk.isEmpty) chunk ++= List(x, y) else chunk += y,
chunks
)
case Nil =>
// terminate recursion
chunks.toSet
case _ => // x != y
recurse(
chars.tail,
chunk = mutable.ListBuffer(),
chunks += chunk.mkString
)
}
}
val chunks = recurse(string, mutable.ListBuffer(), mutable.Set.empty[String])
val max = chunks.map(_.length).max
if (max > 0) chunks.filter( _.length == max ) else Set()
}
}
}
For example, for the given "aeebceeedd" string, both implementations above will build the following set of chunks (repeating characters)
Set("ee", "eee", "dd")
and they will filter those chunks having the maximum length (resulting "eee").
This code should work for any length of string sequence.
public class LongestStringSequqnce {
static String myString = "aaaabbbbcccchhhhiiiiibbbbbbbbbccccccc";
static int largestSequence = 0;
static char longestChar = '\0';
public static void main(String args[]) {
int currentSequence = 1;
char current = '\0';
char next = '\0';
for (int i = 0; i < myString.length() - 1; i++) {
current = myString.charAt(i);
next = myString.charAt(i + 1);
// If character's are in sequence , increase the counter
if (current == next) {
currentSequence += 1;
} else {
if (currentSequence > largestSequence) { // When sequence is
// completed, check if
// it is longest
largestSequence = currentSequence;
longestChar = current;
}
currentSequence = 1; // re-initialize counter
}
}
if (currentSequence > largestSequence) { // Check if last string
// sequence is longest
largestSequence = currentSequence;
longestChar = current;
}
System.out.println("Longest character sequence is of character "
+ longestChar + " and is " + largestSequence + " long");
}
}
Source : http://www.5balloons.info/program-java-code-to-find-longest-character-sequence-in-a-random-string/
if(ctr>ctrstor){
output=i;
}
//storing purposes
ctrstor=ctr;
This looks like the problem. So if you find 8 consecutive characters, it will set output to 8, and proceed. The next time thru, it finds 3 consecutive characters, so doesn't set output, but sets ctrstor. Next time thru it finds 4 consecutive characters, and this will set output to 4
There are few traps in the code that your logic felt in:
Code incorrectly assumes that there is always next character to compare current one.
This fails for string like "a" or the last character in any string.
Code does not store the max count of characters but only the max index (i).
MaxCount is needed to compare the next chars sequence size.
Loop for and loop while repeat the same subset of characters.
Also variable name style makes it harder to understand the code.
After correcting above
public static int runLongestIndex(String setofletters) {
int maxCount = 0;
int maxIndex = 0;
// loops each character in the string
for (int i = 0; i < setofletters.length() - 1; ) {
// new char sequence starts here
char currChar = setofletters.charAt(i);
int count = 1;
int index = i;
while ( (index < setofletters.length() - 1) &&
(currChar == setofletters.charAt(++index)) ) {
count++;
}
if (count > maxCount) {
maxIndex = i;
maxCount = count;
}
i = index;
}
return maxIndex;
}
See Java DEMO
I think you don't need an internal loop:
public static int runLongestIndex(String setofletters) {
if (setofletters == null || setofletters.isEmpty()) {
return -1;
}
int cnt = 1;
char prevC = setofletters.charAt(0);
int maxCnt = 1;
//char maxC = prevC;
int maxRunIdx = 0;
int curRunIdx = 0;
for (int i = 1; i < setofletters.length(); i++){
final char c = setofletters.charAt(i);
if (prevC == c) {
cnt++;
} else {
if (cnt > maxCnt) {
maxCnt = cnt;
//maxC = prevC;
maxRunIdx = curRunIdx;
}
cnt = 1;
curRunIdx = i;
}
prevC = c;
}
if (setofletters.charAt(setofletters.length() - 1) == prevC) {
if (cnt > maxCnt) {
//maxC = prevC;
maxCnt = cnt;
maxRunIdx = curRunIdx;
}
}
return maxRunIdx;
}
and this code:
System.out.println(runLongestIndex("aaakkcccccczz"));
gives you
5
This is how a "colleague" of mine is understanding to write readable code in order to solve this problem, even if this is working :)
public static int count (String str) {
int i = 0;
while(i < str.length()-1 && str.charAt(i)==str.charAt(i+1))
i ++;
return ++i;
}
public static int getLongestIndex(String str){
int output = 0;
for(int i=0, cnt = 1, counter = 0 ; i<str.length() - 1;i += cnt, cnt = count(str.substring(i)), output = (counter = (cnt > counter ? cnt : counter)) == cnt ? i : output);
return output;
}
int indexOfLongestRun(String str) {
char[] ar = str.toCharArray();
int longestRun = 0;
int lastLongestRun = 0;
int index = 0;
for(int i = ar.length-1; i>0; i--){
if(ar[i] == ar[i-1]){
longestRun++;
}else{
if(longestRun > lastLongestRun){
lastLongestRun = longestRun;
longestRun = 0;
index = i;
}
}
}
return index;
Well, the solution a bit depends on the additional requirements. Here is the code which returns the FIRST longest sequence of a repeated character int the given string, meaning if you have a second sequence with the same length you never get it out :(. But still, this is a simple and clear solution here, so good news - it works! :)
string = 'abbbccddddddddeehhhfffzzzzzzzzdddvyy'
longest_sequence = ''
for i in range(len(string)):
is_sequence = True
ch_sequence = ''
while is_sequence:
ch_sequence += string[i]
if i+1 < len(string) and string[i]==string[i+1]:
i += 1
else:
is_sequence = False
if len(ch_sequence) > len(longest_sequence):
longest_sequence = ch_sequence
print (longest_sequence)
#Paolo Angioletti already provided an answer using Scala, but it's more complicated than it needs to be. The idea is not very different from Run-length encoding. Time complexity O(n).
def longestConsecutive(s: String): (Char, Int) = {
Iterator.iterate(('\u0000', 0, 0)) { case (ch, longestRun, i) =>
val run = (i until s.length)
.takeWhile(s(_) == s(i))
.size
if (run > longestRun) (s(i), run, i + run)
else (ch, longestRun, i + run)
}
.dropWhile(i => s.isDefinedAt(i._3))
.take(1)
.map(x => (x._1, x._2))
.next()
}
Tested with:
("s", "ch", "n")
----------------
("", '\u0000', 0),
("a", 'a', 1),
("aabcddbbbea", 'b', 3),
("abcddbbb", 'b', 3),
("cbccca", 'c', 3)
#include <iostream>
#include<algorithm>
using namespace std;
int main() {
string s="abbcccccbbffffffffff";
//cin>>s;
int count=1;
int maxcount=1;
int start=0;
int ps=0;
for (int i=0;i<s.size()-1;i++)
{
if(s.at(i)==s.at(i+1))
{
count +=1;
maxcount=max(maxcount,count);
}
else
{
ps=max(ps,start+count);
count =1;
start=i;
}
}
for(int i=1;i<=maxcount;i++)
{
cout<<s.at(i+ps);
}
// your code goes here
return 0;
}
This is the simplest I can think of and it will print the number of the longest sequenced identical characters in a one line string.
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
scanner.close();
int count = 0;
int curCount = 1;
for (int i = 0; i < s.length() -1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
curCount++;
if (curCount > count) {
count = curCount;
}
}else {
if (curCount > count) {
count = curCount;
}
curCount = 1;
}
}
System.out.println(count);
}
I need to find the last digit in a array and see if it is equal to zero. Here is the code I'm using;
import java.util.Scanner;
public class NrOccurrence
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.print("Enter the integers between 1 and 100: ");
int[] numbers = new int[100], times = new int[100];
boolean zero = false;
while (zero == false)
{
for (int a = 0; a <= numbers.length; a++)
{
numbers[a] = scan.nextInt();
times[a]++;
if (numbers.equals(0))
{
zero = true;
}
}
}
for (int b = 0; b <= numbers.length; b++)
{
System.out.println(numbers[b] + " occurs " + times[b] + " times");
}
scan.close();
}
}
Create a method like this:
private boolean isLastItemZero(int[] numbers)
{
boolean isLastItemZero = false;
if ((numbers != null) && (numbers.length > 0))
{
isLastItemZero = numbers[numbers.length - 1] == 0;
}
return isLastItemZero;
}
And call it once you're done reading in all of the numbers from the user.
First of all for (int a = 0; a <= numbers.length; a++) will give youIndexOutOfBoundsException .Java uses 0 bases indexing which means that an array of size n has indices up to and including n-1. Change it tofor (int a = 0; a < numbers.length; a++) . Same thing here for (int b = 0; b <= numbers.length; b++)
Second i am not sure what you are trying to check here :
if (numbers.equals(0))
{
zero = true;
}
but you could simply do :
if(numbers[i] == 0);
Now if you wanna check if the last element in the array is 0you can simply do:
if(numbers[numbers.length - 1] == 0)
//do something
By definition, if the remainder of a number divided by 10 is 0, then the last digit must be 0. So you just need;
if(numbers[i] % 10 == 0) { zero = true; }
Hope this helps.
I need to factorize a number like 24 to 1,2,2,2,3. My method for that:
static int[] factorsOf (int val) {
int index = 0;
int []numArray = new int[index];
System.out.println("\nThe factors of " + val + " are:");
for(int i=1; i <= val/2; i++)
{
if(val % i == 0)
{
numArray1 [index] = i;
index++;
}
}
return numArray;
}
however, it is not working. Can anyone help me for that?
You have a few errors, you cannot create int array without size. I used array list instead.
static Integer[] factorsOf(int val) {
List<Integer> numArray = new ArrayList<Integer>();
System.out.println("\nThe factors of " + val + " are:");
for (int i = 2; i <= Math.ceil(Math.sqrt(val)); i++) {
if (val % i == 0) {
numArray.add(i);
val /= i;
System.out.print(i + ", ");
}
}
numArray.add(val);
System.out.print(val);
return numArray.toArray(new Integer[numArray.size()]);
}
Full program using int[] according to your request.
public class Test2 {
public static void main(String[] args) {
int val = 5;
int [] result = factorsOf(val);
System.out.println("\nThe factors of " + val + " are:");
for(int i = 0; i < result.length && result[i] != 0; i ++){
System.out.println(result[i] + " ");
}
}
static int[] factorsOf(int val) {
int limit = (int) Math.ceil(Math.sqrt(val));
int [] numArray = new int[limit];
int index = 0;
for (int i = 1; i <= limit; i++) {
if (val % i == 0) {
numArray[index++] = i;
val /= i;
}
}
numArray[index] = val;
return numArray;
}
}
public int[] primeFactors(int num)
{
ArrayList<Integer> factors = new ArrayList<Integer>();
factors.add(1);
for (int a = 2; num>1; )
if (num%a==0)
{
factors.add(a);
num/=a;
}
else
a++;
int[] out = new int[factors.size()];
for (int a = 0; a < out.length; a++)
out[a] = factors.get(a);
return out;
}
Are you looking a more faster way?:
static int[] getFactors(int value) {
int[] a = new int[31]; // 2^31
int i = 0, j;
int num = value;
while (num % 2 == 0) {
a[i++] = 2;
num /= 2;
}
j = 3;
while (j <= Math.sqrt(num) + 1) {
if (num % j == 0) {
a[i++] = j;
num /= j;
} else {
j += 2;
}
}
if (num > 1) {
a[i++] = num;
}
int[] b = Arrays.copyOf(a, i);
return b;
}
Most of the approaches suggested here have 0(n) time complexity. This can be easily resolved using binary search approach with 0(log n) time complexity.
What do you basically are looking for is called Prime Factors (although 1 is not considered among prime factors).
//finding any occurrence of the no by binary search
static int[] primeFactors(int number) {
List<Integer> al = new ArrayList<Integer>();
//since you wanted 1 in the res adn every no will be divided by 1;
al.add(1);
for(int i = 2; i< number; i++) {
while(number%i == 0) {
al.add(i);
number = number/i;
}
}
if(number >2)
al.add(number);
int[] res = new int[al.size()];
for(int i=0; i<al.size(); i++)
res[i] = al.get(i);
return res;
}
Say input is 24, we keep dividing the input by 2 till all multiples of 2 are gone, the increase i to 3
Here is a link to the working code: http://tpcg.io/AWH2TJ
A Working example
public class Main
{
public static void main(String[] args)
{
System.out.println(factorsOf(24));
}
static List<Integer> factorsOf (int val) {
List<Integer> factors = new ArrayList<Integer>();
for(int i=1; i <= val/2; i++)
{
if(val % i == 0)
{
factors.add(i);
}
}
return factors;
}
}
Rework an algorithm for working with big numbers using BigInteger class. Try this:
import java.math.BigInteger;
class NumbersFactorization {
public void printPrimeNumbers(String bigNumber) {
BigInteger number = new BigInteger(bigNumber);
for (BigInteger i = BigInteger.TWO; i.compareTo(number) <= 0; i = i.add(BigInteger.ONE)) {
while(number.remainder(i) == BigInteger.ZERO) {
System.out.print(i + " ");
number = number.divide(i);
}
}
if (number.compareTo(BigInteger.TWO) > 0) System.out.println(number);
}
}
You just missed one step in if. Following code would be correct:
System.out.println("\nThe factors of " + val + " are:");
You can take a square root of val for comparison and start iterator by value 2
if(val % i == 0)
{
numArray1 [index] = i;
val=val/i; //add this
index++;
}
but here you need to check if index is 2,it is prime.