Custom indexOf without String methods - java

I created my own indexOf function. I was wondering if anyone could help me come up with a way to make it more efficient. I am practicing for interviews so the catch is that I cannot use any String methods. I believe the runtime of this method is O(n^2) with space of O(n). Correct me if I am wrong.
Also, I want to ensure the program runs safely and correctly, the only test case I can think of it the length comparison.
code:
public static int myIndexOf(char[] str, char[] substr) {
int len = str.length;
int sublen = substr.length;
int count = 0;
if (sublen > len) {
return -1;
}
for (int i = 0; i < len - sublen + 1; i++) {
for (int j = 0; j < sublen; j++) {
if (str[j+i] == substr[j]) {
count++;
if (count == sublen) {
return i;
}
} else {
count = 0;
break;
}
}
}
return -1;
}

Try here for string searching algorithms:
http://www-igm.univ-mlv.fr/~lecroq/string/
And here for a way to test your implementation:
http://junit.org/

Related

Highly effect find a byte[] is contained by another byte[] [duplicate]

Given a byte array, how can I find within it, the position of a (smaller) byte array?
This documentation looked promising, using ArrayUtils, but if I'm correct it would only let me find an individual byte within the array to be searched.
(I can't see it mattering, but just in case: sometimes the search byte array will be regular ASCII characters, other times it will be control characters or extended ASCII characters. So using String operations would not always be appropriate)
The large array could be between 10 and about 10000 bytes, and the smaller array around 10. In some cases I will have several smaller arrays that I want found within the larger array in a single search. And I will at times want to find the last index of an instance rather than the first.
The simpelst way would be to compare each element:
public int indexOf(byte[] outerArray, byte[] smallerArray) {
for(int i = 0; i < outerArray.length - smallerArray.length+1; ++i) {
boolean found = true;
for(int j = 0; j < smallerArray.length; ++j) {
if (outerArray[i+j] != smallerArray[j]) {
found = false;
break;
}
}
if (found) return i;
}
return -1;
}
Some tests:
#Test
public void testIndexOf() {
byte[] outer = {1, 2, 3, 4};
assertEquals(0, indexOf(outer, new byte[]{1, 2}));
assertEquals(1, indexOf(outer, new byte[]{2, 3}));
assertEquals(2, indexOf(outer, new byte[]{3, 4}));
assertEquals(-1, indexOf(outer, new byte[]{4, 4}));
assertEquals(-1, indexOf(outer, new byte[]{4, 5}));
assertEquals(-1, indexOf(outer, new byte[]{4, 5, 6, 7, 8}));
}
As you updated your question: Java Strings are UTF-16 Strings, they do not care about the extended ASCII set, so you could use string.indexOf()
Google's Guava provides a Bytes.indexOf(byte[] array, byte[] target).
Using the Knuth–Morris–Pratt algorithm is the most efficient way.
StreamSearcher.java is an implementation of it and is part of Twitter's elephant-bird project.
It is not recommended to include this library since it is rather sizable for using just a single class.
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
/**
* An efficient stream searching class based on the Knuth-Morris-Pratt algorithm.
* For more on the algorithm works see: http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm.
*/
public class StreamSearcher
{
private byte[] pattern_;
private int[] borders_;
// An upper bound on pattern length for searching. Results are undefined for longer patterns.
#SuppressWarnings("unused")
public static final int MAX_PATTERN_LENGTH = 1024;
StreamSearcher(byte[] pattern)
{
setPattern(pattern);
}
/**
* Sets a new pattern for this StreamSearcher to use.
*
* #param pattern the pattern the StreamSearcher will look for in future calls to search(...)
*/
public void setPattern(byte[] pattern)
{
pattern_ = Arrays.copyOf(pattern, pattern.length);
borders_ = new int[pattern_.length + 1];
preProcess();
}
/**
* Searches for the next occurrence of the pattern in the stream, starting from the current stream position. Note
* that the position of the stream is changed. If a match is found, the stream points to the end of the match -- i.e. the
* byte AFTER the pattern. Else, the stream is entirely consumed. The latter is because InputStream semantics make it difficult to have
* another reasonable default, i.e. leave the stream unchanged.
*
* #return bytes consumed if found, -1 otherwise.
*/
long search(InputStream stream) throws IOException
{
long bytesRead = 0;
int b;
int j = 0;
while ((b = stream.read()) != -1)
{
bytesRead++;
while (j >= 0 && (byte) b != pattern_[j])
{
j = borders_[j];
}
// Move to the next character in the pattern.
++j;
// If we've matched up to the full pattern length, we found it. Return,
// which will automatically save our position in the InputStream at the point immediately
// following the pattern match.
if (j == pattern_.length)
{
return bytesRead;
}
}
// No dice, Note that the stream is now completely consumed.
return -1;
}
/**
* Builds up a table of longest "borders" for each prefix of the pattern to find. This table is stored internally
* and aids in implementation of the Knuth-Moore-Pratt string search.
* <p>
* For more information, see: http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm.
*/
private void preProcess()
{
int i = 0;
int j = -1;
borders_[i] = j;
while (i < pattern_.length)
{
while (j >= 0 && pattern_[i] != pattern_[j])
{
j = borders_[j];
}
borders_[++i] = ++j;
}
}
}
Is this what you are looking for?
public class KPM {
/**
* Search the data byte array for the first occurrence of the byte array pattern within given boundaries.
* #param data
* #param start First index in data
* #param stop Last index in data so that stop-start = length
* #param pattern What is being searched. '*' can be used as wildcard for "ANY character"
* #return
*/
public static int indexOf( byte[] data, int start, int stop, byte[] pattern) {
if( data == null || pattern == null) return -1;
int[] failure = computeFailure(pattern);
int j = 0;
for( int i = start; i < stop; i++) {
while (j > 0 && ( pattern[j] != '*' && pattern[j] != data[i])) {
j = failure[j - 1];
}
if (pattern[j] == '*' || pattern[j] == data[i]) {
j++;
}
if (j == pattern.length) {
return i - pattern.length + 1;
}
}
return -1;
}
/**
* Computes the failure function using a boot-strapping process,
* where the pattern is matched against itself.
*/
private static int[] computeFailure(byte[] pattern) {
int[] failure = new int[pattern.length];
int j = 0;
for (int i = 1; i < pattern.length; i++) {
while (j>0 && pattern[j] != pattern[i]) {
j = failure[j - 1];
}
if (pattern[j] == pattern[i]) {
j++;
}
failure[i] = j;
}
return failure;
}
}
To save your time in testing:
http://helpdesk.objects.com.au/java/search-a-byte-array-for-a-byte-sequence
gives you code that works if you make computeFailure() static:
public class KPM {
/**
* Search the data byte array for the first occurrence
* of the byte array pattern.
*/
public static int indexOf(byte[] data, byte[] pattern) {
int[] failure = computeFailure(pattern);
int j = 0;
for (int i = 0; i < data.length; i++) {
while (j > 0 && pattern[j] != data[i]) {
j = failure[j - 1];
}
if (pattern[j] == data[i]) {
j++;
}
if (j == pattern.length) {
return i - pattern.length + 1;
}
}
return -1;
}
/**
* Computes the failure function using a boot-strapping process,
* where the pattern is matched against itself.
*/
private static int[] computeFailure(byte[] pattern) {
int[] failure = new int[pattern.length];
int j = 0;
for (int i = 1; i < pattern.length; i++) {
while (j>0 && pattern[j] != pattern[i]) {
j = failure[j - 1];
}
if (pattern[j] == pattern[i]) {
j++;
}
failure[i] = j;
}
return failure;
}
}
Since it is always wise to test the code that you borrow, you may start with:
public class Test {
public static void main(String[] args) {
do_test1();
}
static void do_test1() {
String[] ss = { "",
"\r\n\r\n",
"\n\n",
"\r\n\r\nthis is a test",
"this is a test\r\n\r\n",
"this is a test\r\n\r\nthis si a test",
"this is a test\r\n\r\nthis si a test\r\n\r\n",
"this is a test\n\r\nthis si a test",
"this is a test\r\nthis si a test\r\n\r\n",
"this is a test"
};
for (String s: ss) {
System.out.println(""+KPM.indexOf(s.getBytes(), "\r\n\r\n".getBytes())+"in ["+s+"]");
}
}
}
Copied almost identical from java.lang.String.
indexOf(char[],int,int,char[]int,int,int)
static int indexOf(byte[] source, int sourceOffset, int sourceCount, byte[] target, int targetOffset, int targetCount, int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
byte first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first)
;
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++)
;
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}
package org.example;
import java.util.List;
import org.riversun.finbin.BinarySearcher;
public class Sample2 {
public static void main(String[] args) throws Exception {
BinarySearcher bs = new BinarySearcher();
// UTF-8 without BOM
byte[] srcBytes = "Hello world.It's a small world.".getBytes("utf-8");
byte[] searchBytes = "world".getBytes("utf-8");
List<Integer> indexList = bs.searchBytes(srcBytes, searchBytes);
System.out.println("indexList=" + indexList);
}
}
so it results in
indexList=[6, 25]
So,u can find the index of byte[] in byte[]
Example here on Github at: https://github.com/riversun/finbin
Several (or all?) of the examples posted here failed some Unit tests so I am posting my version along with the aforementioned tests over here. All of the Unit tests are BASED upon the requirement that Java's String.indexOf() always gives us the right answer!
// The Knuth, Morris, and Pratt string searching algorithm remembers information about
// the past matched characters instead of matching a character with a different pattern
// character over and over again. It can search for a pattern in O(n) time as it never
// re-compares a text symbol that has matched a pattern symbol. But, it does use a partial
// match table to analyze the pattern structure. Construction of a partial match table
// takes O(m) time. Therefore, the overall time complexity of the KMP algorithm is O(m + n).
public class KMPSearch {
public static int indexOf(byte[] haystack, byte[] needle)
{
// needle is null or empty
if (needle == null || needle.length == 0)
return 0;
// haystack is null, or haystack's length is less than that of needle
if (haystack == null || needle.length > haystack.length)
return -1;
// pre construct failure array for needle pattern
int[] failure = new int[needle.length];
int n = needle.length;
failure[0] = -1;
for (int j = 1; j < n; j++)
{
int i = failure[j - 1];
while ((needle[j] != needle[i + 1]) && i >= 0)
i = failure[i];
if (needle[j] == needle[i + 1])
failure[j] = i + 1;
else
failure[j] = -1;
}
// find match
int i = 0, j = 0;
int haystackLen = haystack.length;
int needleLen = needle.length;
while (i < haystackLen && j < needleLen)
{
if (haystack[i] == needle[j])
{
i++;
j++;
}
else if (j == 0)
i++;
else
j = failure[j - 1] + 1;
}
return ((j == needleLen) ? (i - needleLen) : -1);
}
}
import java.util.Random;
class KMPSearchTest {
private static Random random = new Random();
private static String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
#Test
public void testEmpty() {
test("", "");
test("", "ab");
}
#Test
public void testOneChar() {
test("a", "a");
test("a", "b");
}
#Test
public void testRepeat() {
test("aaa", "aaaaa");
test("aaa", "abaaba");
test("abab", "abacababc");
test("abab", "babacaba");
}
#Test
public void testPartialRepeat() {
test("aaacaaaaac", "aaacacaacaaacaaaacaaaaac");
test("ababcababdabababcababdaba", "ababcababdabababcababdaba");
}
#Test
public void testRandomly() {
for (int i = 0; i < 1000; i++) {
String pattern = randomPattern();
for (int j = 0; j < 100; j++)
test(pattern, randomText(pattern));
}
}
/* Helper functions */
private static String randomPattern() {
StringBuilder sb = new StringBuilder();
int steps = random.nextInt(10) + 1;
for (int i = 0; i < steps; i++) {
if (sb.length() == 0 || random.nextBoolean()) { // Add literal
int len = random.nextInt(5) + 1;
for (int j = 0; j < len; j++)
sb.append(alphabet.charAt(random.nextInt(alphabet.length())));
} else { // Repeat prefix
int len = random.nextInt(sb.length()) + 1;
int reps = random.nextInt(3) + 1;
if (sb.length() + len * reps > 1000)
break;
for (int j = 0; j < reps; j++)
sb.append(sb.substring(0, len));
}
}
return sb.toString();
}
private static String randomText(String pattern) {
StringBuilder sb = new StringBuilder();
int steps = random.nextInt(100);
for (int i = 0; i < steps && sb.length() < 10000; i++) {
if (random.nextDouble() < 0.7) { // Add prefix of pattern
int len = random.nextInt(pattern.length()) + 1;
sb.append(pattern.substring(0, len));
} else { // Add literal
int len = random.nextInt(30) + 1;
for (int j = 0; j < len; j++)
sb.append(alphabet.charAt(random.nextInt(alphabet.length())));
}
}
return sb.toString();
}
private static void test(String pattern, String text) {
try {
assertEquals(text.indexOf(pattern), KMPSearch.indexOf(text.getBytes(), pattern.getBytes()));
} catch (AssertionError e) {
System.out.println("FAILED -> Unable to find '" + pattern + "' in '" + text + "'");
}
}
}
Java strings are composed of 16-bit chars, not of 8-bit bytes. A char can hold a byte, so you can always make your byte arrays into strings, and use indexOf: ASCII characters, control characters, and even zero characters will work fine.
Here is a demo:
byte[] big = new byte[] {1,2,3,0,4,5,6,7,0,8,9,0,0,1,2,3,4};
byte[] small = new byte[] {7,0,8,9,0,0,1};
String bigStr = new String(big, StandardCharsets.UTF_8);
String smallStr = new String(small, StandardCharsets.UTF_8);
System.out.println(bigStr.indexOf(smallStr));
This prints 7.
However, considering that your large array could be up to 10,000 bytes, and the small array is only ten bytes, this solution may not be the most efficient, for two reasons:
It requires copying your big array into an array that is twice as large (same capacity, but with char instead of byte). This triples your memory requirements.
String search algorithm of Java is not the fastest one available. You may get sufficiently faster if you implement one of the advanced algorithms, for example, the Knuth–Morris–Pratt one. This could potentially bring the execution speed down by a factor of up to ten (the length of the small string), and will require additional memory that is proportional to the length of the small string, not the big string.
For a little HTTP server I am currently working on, I came up with the following code to find boundaries in a multipart/form-data request. Hoped to find a better solution here, but i guess I'll stick with it. I think it is as efficent as it can get (quite fast and uses not much ram). It uses the input bytes as ring buffer, reads the next byte as soon as it does not match the boundary and writes the data after the first full cycle into the output stream. Of course can it be changed for byte arrays instead of streams, as asked in the question.
private boolean multipartUploadParseOutput(InputStream is, OutputStream os, String boundary)
{
try
{
String n = "--"+boundary;
byte[] bc = n.getBytes("UTF-8");
int s = bc.length;
byte[] b = new byte[s];
int p = 0;
long l = 0;
int c;
boolean r;
while ((c = is.read()) != -1)
{
b[p] = (byte) c;
l += 1;
p = (int) (l % s);
if (l>p)
{
r = true;
for (int i = 0; i < s; i++)
{
if (b[(p + i) % s] != bc[i])
{
r = false;
break;
}
}
if (r)
break;
os.write(b[p]);
}
}
os.flush();
return true;
} catch(IOException e) {e.printStackTrace();}
return false;
}

Leetcode - Longest Common Prefix - Why is my runtime so slow compared to the solution?

Question: Write a function to find the longest common prefix string amongst an array of strings.
This is a easy question from leetcode and below is my answer VS. the solution answer. The problem is: my answer beats 1.17% of the runtime speed and the solution beats 79.65%. Why is my code so slow?
Our code are pretty much similar until we start to manipulate the initial common string. The solution does this by calling indexof and substring function in String class and mine does it by using a findCommon function, which is defined by me.
Solution:
public String longestCommonPrefix(String[] strs) {
if(strs == null || strs.length == 0) return "";
String pre = strs[0];
int i = 1;
while(i < strs.length){
while(strs[i].indexOf(pre) != 0)
pre = pre.substring(0,pre.length()-1);
i++;
}
return pre;
}
This is mine:
public static String longestCommonPrefix(String[] strs){
if(strs == null || strs.length == 0)
return "";
String result = strs[0];
for(int index = 1; index < strs.length; index++)
result = findCommon(result, strs[index]);
return result;
}
public static String findCommon(String a, String b){
String common = "";
for(int index = 0; index < Math.min(a.length(), b.length()); index++)
{
if(a.charAt(index) == b.charAt(index))
common += a.charAt(index);
else
break;
}
return common;
}
In my opinion, the solution code only looks simpler because the functions are defined in String library. But it doesn't mean they don't exist.
Take a look at how you're building up the prefix string:
String common = "";
for(int index = 0; index < Math.min(a.length(), b.length()); index++)
{
if(a.charAt(index) == b.charAt(index))
common += a.charAt(index);
else
break;
}
return common;
Every time you execute
common += a.charAt(index);
Java has to create a brand new String object formed by tacking a new character onto the end of the existing string common. This means that the cost of making a prefix string of length p ends up being O(p2). If you have n total strings, then the runtime of your program will be something like O(np2).
Contrast this against the reference solution:
pre = pre.substring(0,pre.length()-1);
In many Java implementations, the act of creating a substring takes time O(1) because the new string can share the underlying character array with the original string (with some indices tweaked to account for the new start index). That means that the cost of working through p prefixes would be O(p) rather than O(p2), which could lead to a large increase in performance for longer strings.
I user trie to solve that problem. You can try to user trie
#define MAX 30 //the total number of alphabet is 26, a...z
struct DicTrie{
bool isTerminal;//是否是单词结束标志
int count; //当前字符串出现次数
int branchCount; //计数当前节点的孩子数
struct DicTrie *next[MAX ]; //每个节点 最多 有 MAX 个孩子节点 结构体嵌套
};
int insertTrie(struct DicTrie *root ,char *targetString)
{
if (!targetString) {
return 0;
}
int len = strlen(targetString);
if (len <= 0) {
return 0;
}
struct DicTrie *head = root;
for (int i = 0; i < len; i ++) {
int res = (int)(targetString[i] - 'a');//当前小写字母对应数字
if (head->next[res] == NULL) { //如果是空节点
head->next[res] = (struct DicTrie *)malloc(sizeof(struct DicTrie));//new DicTrie;//则插入新节点元素
head = head->next[res]; //更新头指针 并初始化
head->count = 0; //
for (int j = 0; j < MAX; j ++) {
head->next[j] = NULL;
head->isTerminal = false;
}
head->branchCount = 1;//一个分支
} else {
head = head->next[res];
head->branchCount ++;//分支累计
}
}
head->count ++;//每次插入一个,响应计数都增加1
head->isTerminal = true;
return head->count;
}
char* longestCommonPrefix(char** strs, int strsSize) {
int len = strsSize;
//边界处理
if (len == 0) {
return "";
}
if (len == 1) {
return strs[0];
}
//组织字典树
struct DicTrie *root = NULL;
root = (struct DicTrie *)malloc(sizeof(struct DicTrie));
root->count = 0;
root->branchCount = 0;
for (int i = 0; i < MAX; i ++) {
root->next[i] = NULL; // 空节点
root->isTerminal = false; //
}
//
for (int i = 0;i < len; i ++) {
insertTrie(root, strs[i]);
}
//
int preIndex = 0;
struct DicTrie *head = root;
bool isFlag = false;
int i = 0;
int count = strlen(strs[0]);//任意一字符串都可以 从strs[0]中查即可
for (preIndex = 0; preIndex< count; preIndex ++) {
int targetIndex = strs[0][preIndex] - 'a';
head = head->next[targetIndex];
if (head->branchCount == len) {
i ++;//拿到合法前缀的计数
isFlag = true;
}
}
if (isFlag) {
preIndex = i;
} else {
preIndex = 0;
}
strs[0][preIndex] = '\0';
return strs[0];
}
the runtime speed is ok.

For-loop is executed only once?

I'm implementing Insertionsort for university. My code works in theory, but my for-loop is executed only once instead of books.size() (which is 5, I've tested that). I tried it using the number 5, but it won't work and I'm kind of desperate because I can't seem to find the error.
Here is my code:
static void sort(LinkedList<Book> books)
{
int i;
for ( i = 0; i < books.size(); i++)
{
Book temp = books.get(i);
books.remove(i);
for (int j = 0; j < books.size(); j++) {
if (books.get(j).compareTo(temp) > 0) {
books.add(j, temp);
return;
}
}
books.add(temp);
}
}
The compareTo function of the Book-Class looks like the following:
public int compareTo(Book other)
{
int iAutor = autor.compareTo(other.getAutor());
if (iAutor != 0)
return iAutor;
else
{
int iTitel = titel.compareTo(other.getTitel());
if (iTitel != 0)
return iTitel;
else
{
if (this.auflage < other.getAuflage())
return -1;
else if (this.auflage > other.getAuflage())
return 1;
else
return 0;
}
}
}
Am I simply blind?
You need to swap return for break and fix the logic to avoid adding the book twice. There may be more elegant ways than this, but it should work:
int i;
for ( i = 0; i < books.size(); i++)
{
Book temp = books.get(i);
books.remove(i);
bool added = false;
for (int j = 0; j < books.size(); j++) {
if (books.get(j).compareTo(temp) > 0) {
books.add(j, temp);
added = true;
break;
}
}
if (!added) {
books.add(temp);
}
}
Well, I found out how to solve it, just if someone has the same problem (don't think that will happen, but it's a good habit I hope).
As #Klitos Kyriacou pointed out right, I had a twist in my thoughts about the process of Insertionsorting.
The solution is changing the loops in the following:
static void sort(LinkedList<Book> books) {
Book temp;
for (int counter = 0; counter < books.size(); counter++) {
temp = books.get(counter);
for (int position = 0; position < counter; position++)
{
if (temp.compareTo(books.get(position)) < 0)
{
books.remove(counter);
books.add(position, temp);
break;
}
}
}
}

Codility PermCheck Solution isn't working on a few data sets

Trying to solve codility lessons for practice and working on this.
Written my code in Java and tested the code on a wide range of inputs, however the code fails for extreme_min_max, single and double in the codility test results.
Assumption given:
N is an integer within the range [1..100,000].
Each element of array A is an integer within the range [1..1,000,000,000].
Explanation of my code:
1. Sort the given array.
2. Iterate over each element in the array to find the difference between every consecutive pair. If the difference is not 1, Then its not a perm hence return 0. In case there is only one element in the array, return 1.
Can anyone please help me find out the bug(s) in my code?
My code:
public int solution(int[] A)
{
if(A.length == 1)
return 1;
Arrays.sort(A);
for (int i = 0; i < A.length-1; i++)
{
long diff = Math.abs(A[i] - A[i+1]);
if(diff!=1)
return 0;
}
return 1;
}
Here is simple and better implementation which runs in O(N) time complexity and takes O(N) space complexity.
public int solution(int[] A)
{
int size = A.length;
int hashArray[] = new int[size+1];
for (int i = 0; i < size; i++)
{
if(A[i]>size)
return 0;
else
hashArray[A[i]]+=1;
}
for(int i=1;i<=size;i++)
if(hashArray[i]!=1)
return 0;
return 1;
}
Try this in C# (Score 100%) :
using System;
using System.Linq;
class Solution {
public int solution(int[] A) {
if (A.Any(x => x == 0)) { return 0; }
var orderSelect = A.OrderBy(x => x).GroupBy(x => x);
if (orderSelect.Any(x => x.Count() > 1)) { return 0; }
var res = Enumerable.Range(1, A.Length).Except(A);
return res.Any() ? 0 : 1;
}
}
Pretty simple:
Your code doesn't check this condition:
A permutation is a sequence containing each element from 1 to N once, and only once.
Ensure that the first element after sorting is 1, and everything should work.
I'm not big on Java syntax, but what you want to do here is:
Create an array temp the length of A - initialized to 0.
Go over A and do temp[A[i]]++.
Go over temp, and if any place in the array is not 1, return false.
If duplicate exists - return 0 I have implemented with 100% pass
https://codility.com/demo/results/trainingWX2E92-ASF/
public static int permCheck(int A[]){
Set<Integer> bucket = new HashSet<Integer>();
int max = 0;
int sum=0;
for(int counter=0; counter<A.length; counter++){
if(max<A[counter]) max=A[counter];
if(bucket.add(A[counter])){
sum=sum+A[counter];
}
else{
return 0;
}
}
System.out.println(max+"->"+sum);
int expectedSum = (max*(max+1))/2;
if(expectedSum==sum)return 1;
return 0;
}
Here's my first 100% code.
I can't say if it's the fastest but it seems all correct -- watch the double OR ( || ) condition.
import java.util.Arrays;
class Solution
{
public int solution(int[] A)
{
int i = 0;
int size = A.length;
if ( size > 0 && size < 100001)
{
// Sort the array ascending:
Arrays.sort(A);
// Check each element:
for(i = 0; i < size; i++)
if ( A[i] > size || A[i] != (i + 1) )
return 0;
return 1;
}
return 0;
}
}
EDIT
Actually, we need not worry about valid first element data (i.e. A[i] > 0) because, after sorting, a valid perm array must have A[0] = 1 and this is already covered by the condition A[i] = i + 1.
The upper limit for array entries (> 1,000,000,000) is restricted further by the limit on the array size itself (100,000) and we must check for conformity here as there will be a Codility test for this. So I have removed the lower limit condition on array entries.
Below code runs and gave me a 100%, the time complexity is O(n):
private static int solution(int[] A) {
int isPermutation = 1; // all permutations start at 1
int n = A.length;
Arrays.sort(A);
if (n == 0) return 0; // takes care of edge case where an empty array is passed
for (int i = 0; i < n; i++) {
if (A[i] != isPermutation) { //if current array item is not equals to permutation, return 0;
return 0;
}
isPermutation++;
}
return 1;
}
100% score with complexity O(N)
public int solution(int[] A) {
int res = 1;
if (A.length == 1 && A[0]!=1)
return 0;
int[] B = new int[A.length];
for (int j : A) {
int p = j - 1;
if (A.length > p)
B[p] = j;
}
for (int i = 0; i < B.length - 1; i++) {
if (B[i] + 1 != B[i + 1]) {
res = 0;
break;
}
}
return res;
}

compare the last names of two students in a directory

I'm trying to compare the last names of two students in a directory, I'm doing this by overriding the compareTo method. The following code does not reflect exactly what I'm wanting to do here, the return value is just a placeholder for now. It is saying it won't compile because it cannot find the symbol for subString(int) in class String.
for (int i = 0; i < this.getLastName().length(); i++) {
if (!this.getLastName().subString(i).equals(s.getLastName().subString(i))) {
return 1;
}
}
Update: I appreciate y'all pointing out my idiocy in case sensitivity (no really, thanks) here's an update to where I'm at in the code. I think I can take it from here.
#Override
public int compareTo(Student s) {
for (int i = 0; i < this.getLastName().length(); i++) {
if (!this.getLastName().equals(s.getLastName())) {
for(int j = 0; j < this.getLastName().length() || j < s.getLastName().length(); j++) {
if (this.getLastName().charAt(j) < s.getLastName().charAt(j)) {
return 1;
}
else {
return -1;
}
}
}
}
looking at it again, I don't even need that first for loop.
and here's the finished method.
#Override
public int compareTo(Student s) {
if (!this.getLastName().equals(s.getLastName())) {
for(int j = 0; j < this.getLastName().length() || j < s.getLastName().length(); j++) {
if (this.getLastName().charAt(j) < s.getLastName().charAt(j)) {
return 1;
}
else if (this.getLastName().charAt(j) > s.getLastName().charAt(j)) {
return -1;
}
}
}
if (!this.getFirstName().equals(s.getFirstName())) {
for (int i = 0; i < this.getLastName().length() || i < s.getLastName().length(); i++) {
if (this.getFirstName().charAt(i) < s.getFirstName().charAt(i)) {
return 1;
}
else if (this.getFirstName().charAt(i) > s.getFirstName().charAt(i)) {
return -1;
}
}
}
return 0;
}
The simple way to compare two Java strings is to use the String.compareTo(String). You don't need to implement that yourself using loops. (Or at least, not in a real world context.)
If you want to order by lastname then firstname:
call `compareTo` on the last name string
- if the result is non zero, return it
- if the result is zero, compare the first name string.
I'll leave you to figure out the rest ... since this is clearly a "learning exercise".
Not sure why you want to reinvent the wheel. Stephen C was trying to point out that you can achieve the same result like this:
#Override
public int compareTo(Student that) {
int compare = this.getLastName().compareTo(that.getLastName());
if (compare == 0) {
compare = this.getFirstName().compareTo(that.getFirstName());
}
return compare;
}

Categories

Resources